2012-10-03 11 views
6

Ich habe eine lokale SQLite-DatenbankSQLite - Schnellste Möglichkeit zum Lesen von Daten aus der SQLite-Datenbank?

TABELLE DETAILS

-- Describe PREFIX_LIST 
CREATE TABLE PREFIX_LIST(ITEM VARCHAR(25) PRIMARY KEY) 

-- Describe SUFFIX_LIST 
CREATE TABLE SUFFIX_LIST(ITEM VARCHAR(25) PRIMARY KEY) 

-- Describe VALID_LIST 
CREATE TABLE VALID_LIST (
    "PART1" TEXT, 
    "PART2" TEXT, 
    PRIMARY KEY(PART1, PART2) 
) 

jetzt ist diese Liste wirklich riesig, und ich brauche, müssen Daten von ihm zu speichern.

Hier ist meine Implementierung.

SQLiteConnection con = null; 
SQLiteCommand cmd = null; 
Connect(DbPath, ref con, ref cmd); 

cmd.CommandText = 
    "SELECT PART1 || '@' || PART2 FROM VALID_LIST 
WHERE NOT EXISTS 
    (SELECT * FROM PREFIX_LIST WHERE VALID_LIST.PART1 LIKE '%' || ITEM || '%') 
    AND NOT EXISTS 
    (SELECT * FROM SUFFIX_LIST WHERE VALID_LIST.PART2 LIKE '%' || ITEM || '%')"; 

var reader = cmd.ExecuteReader(); 

if (reader.HasRows) 
{ 
    string savePath; 

    if (SaveTextFile(out savePath) == DialogResult.OK) 
    { 
     TextWriter writer = new StreamWriter(savePath); 
     while (reader.Read()) 
     { 
      writer.WriteLine(reader.GetString(0)); 
     } 
     writer.Close(); 
     writer.Dispose(); 
    } 

} 

reader.Close(); 
reader.Dispose(); 
cmd.Dispose(); 
con.Close(); 
con.Dispose(); 

MessageBox.Show("List Saved!.", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information); 

Ich brauche eine bessere Möglichkeit, ich kann Liste schneller speichern. Gesamt Einträge in VALID_LIST ist 2639117

und es dauerte 15 Minuten, um es für die obige SQL-Abfrage zu speichern!

bitte LMK, wenn die SQL-Abfrage optimiert werden kann!

Vielen Dank im Voraus

+2

Correlated Subquery + 'LIKE' = enorme Performance-Hit – cdhowie

+0

@cdhowie - ich weiß, aber was sind andere Lösung? Ich denke, Abfrage muss irgendwie optimiert werden! –

+0

Ich glaube nicht, dass es eine einfache Möglichkeit gibt, dies zu optimieren, ohne Ihr Schema vollständig zu ändern. – cdhowie

Antwort

6

Abfragen mit LIKE wird sehr langsam in der Regel sein, wenn der Platzhalter mit dem Suffix angebracht ist. Ein Prädikat wie LIKE '%foo' kann nicht über eine typische String-Indizierung indiziert werden.

Sie können jedoch schwere LIKE Verwendung in sqlite mit seiner full text search (FTS) -Funktion ersetzen.

Die FTS3 und FTS4 Erweiterungsmodule ermöglicht es Benutzern, spezielle Tabellen mit einem eingebauten in Volltextindex (im Folgenden „FTS-Tabellen“) zu erstellen. Der Volltextindex ermöglicht es dem Benutzer, die Datenbank effizient nach alle Zeilen abzufragen, die ein oder mehrere Wörter (im Folgenden "Token") enthalten, auch wenn die Tabelle viele große Dokumente enthält.

Sie haben an example, die in Bezug auf Leistung auf Ihren Anwendungsfall vielversprechend aussehen.

CREATE VIRTUAL TABLE enrondata1 USING fts3(content TEXT);  /* FTS3 table */ 
CREATE TABLE enrondata2(content TEXT);      /* Ordinary table * 

SELECT count(*) FROM enrondata1 WHERE content MATCH 'linux'; /* 0.03 seconds */ 
SELECT count(*) FROM enrondata2 WHERE content LIKE '%linux%'; /* 22.5 seconds */ 
+0

Ich denke, Sie haben es rückwärts - Präfixe können Indizes verwenden, aber Suffixe können nicht. – cdhowie

+0

@cdhowie Ich stimme zu, ich bezog mich auf, wo der Platzhalter angebracht wurde. Ich habe meine Antwort geklärt. –

+0

Ich sehe was du jetzt meintest. Es war ein wenig mehrdeutig, danke für die Klärung. – cdhowie

2

Verwenden Sie Volltextsuche.

Damit dies funktioniert, müssen die Werte in PREFIX und SUFFIX in Token umgewandelt werden (sie müssen separate Wörter sein) und das ITEM, das Sie abgleichen wollen, muss ein eindeutiges Token in einem dieser Werte sein (kein Teil) eines Wortes oder zwei Wörter zusammen). Zum Beispiel müssen die Saiten in PREFIX und SUFFIX etwas wie 'ROT BLAU GRÜN' oder 'HUND, KATZE, CAPYBARA' sein und die Werte für ITEM müssen ROT, BLAU, GRÜN, HUNDE, KATZE oder CAPYBARA sein.

Wenn diese Bedingungen erfüllt sind, können Sie die Volltextsuche aktivieren, diese Tabellen als Volltexttabellen neu erstellen und LIKE (und die Platzhalter) durch MATCH ersetzen. In diesem Fall behält SQLite den Index für alle Token, die in PREFIX oder SUFFIX enthalten sind, und dieser Teil der Suche wird viel, viel schneller sein.

Leider erfordert die Aktivierung von FTS in SQlite die Kompilierung des Produkts aus dem Quellcode mit einem oder mehreren gesetzten Kompilierungsflags. Ich habe keine Erfahrung damit.

+0

thnx für alle Infos! sieht so aus, als müsste ich bei meiner lösung atm bleiben, auch wenn es langsamer ist! –

+0

Stimmt es, dass Ihr passendes Item gegen einzelne Wörter? Wenn dies der Fall ist, legen Sie die Wörter nacheinander in ihre eigenen Reihen. Sie können diese Arbeit sehr schnell erledigen. –

+0

leid für mein schlechtes Englisch, aber was ich versuche, über SQL zu tun ist, stellen Sie sicher, dass alle meine Artikel in valid_list.part1 nicht alle relevanten Spiele teilweise aus dem Artikel in prefix_list.item –

0

Ich bin mir nicht sicher, ob dies das ist, was Sie wollen, aber es wird helfen, den Schreibprozess zu beschleunigen. Versuchen Sie, die Strings, die Sie aus der Datenbank lesen, in einem String Builder zu erstellen und dann in die Datei zu schreiben. Zum Beispiel können Sie 100k Zeichenfolge lesen und dann diese 100k in die Datei auf einmal schreiben.

StringBuilder builder = new StringBuilder(); 
    int count = 0; //to limit the number of rows stored in string builder. 
    while (reader.Read()) 
    { 

     builder.AppendLine(reader.GetString(0)); 
     count++; 

     //store every 100k or so rows at once. 
     //This number depends on how much RAM 
     //you can allocate towards storing the string of rows. 
     //If you have 2GB of free RAM 
     //this number can easily be 1 million but it always depends on the 
     //size of each string stored in database. 
     if(count == 100000) 
     { 
      File.AppendAllText(path, builder.ToString()); //Append all rows to the file 
      builder.Clear(); //clear the string for next 100k rows of data 
      count = 0; //Clear the counter value 
     } 
     count++ 
    } 

Lassen Sie mich wissen, wenn es geholfen hat.

Verwandte Themen