2012-07-10 5 views
8

Ich muss einige Daten auf Basis eines Schlüsselwortes abrufen, die Abfrage wird zu 100% genau getestet, aber das Problem ist, dass das Laden der reader ist ziemlich langsam. Ich habe versucht, diese Abfrage durch eine zu ersetzen, die inner join s überhaupt nicht enthält, und das Laden war ziemlich schnell. Ich frage mich also, warum DataTable.Load() so viel Zeit braucht, weil ich nur eine Spalte auswähle. Ist es die SQLite 's ExecuteReader, die die ganzen Ergebnisse und nicht nur die eine Spalte lädt?DataTable Reader Laden ist sehr langsam

Vor der Verwendung der DataTable betrug die durchschnittliche Ausführungszeit für jede reader.Read() 7 Sekunden.

Dies ist mein Code:

_database.Connect(); 

var selectCommand = new SQLiteCommand(
@"SELECT A.ID AS MY_ID FROM MD 
INNER JOIN TMD ON MD.ID = TMD.ID_MD 
INNER JOIN TR ON TR.ID = TMD.ID_TR 
INNER JOIN P ON P.ID = TR.ID_P 
INNER JOIN DP ON DP.ID_P = P.ID 
INNER JOIN CD ON CD.ID = DP.ID_CD 
WHERE CD.DESC = @desc" 
); 

selectCommand.Parameters.AddWithValue("@desc", value); 

using (DbDataReader reader = _database.ExecuteQuery(selectCommand)) 
{ 
    DataTable data = new DataTable("MyData"); 
    data.Load(reader); 
} 
_database.Disconnect(); 
+1

Es klingt wie Ihre Abfrage ist einfach langsam. Gibt es eine andere Möglichkeit, auf Ihre Tabellen zuzugreifen, sodass Sie nicht so viele Joins durchführen müssen? – Tejs

+0

Ich wusste, das würde weh tun .. Leider müssen wir die 2 Tabellen auf einem der Felder verbinden. Diese Verknüpfungen stellen die einzige Verbindung zwischen ihnen dar, wenn das aktuelle DB-Schema angegeben wird. – iCantSeeSharp

+0

Was ist '_database' und warum hat es Methoden wie' Connect' und 'Disconnect'? Erfinde das Rad nicht neu. Sie sollten auch eine 'using-Anweisung' für Ihre Verbindung verwenden, um sicherzustellen, dass sie so schnell wie möglich" geschlossen "wird. Ist dies eine Multithreading-Umgebung wie ASP.NET? –

Antwort

2

The SQLite Query Planner bietet einige Hinweise zur Abfrageoptimierung für SQLite.

einige Elemente, die auf Ihre Frage anwenden können:

1.) Durch die Implementierung in SQLite Sie das mehrere schließt sich neu zu ordnen versuchen könnte:

Die aktuelle Implementierung von SQLite verwendet nur Schleife verbindet. Das heißt, dass Joins als verschachtelte Schleifen implementiert sind. Die Standardreihenfolge der verschachtelten Schleifen in einem Join ist für die äußerste linke Tabelle in der FROM-Klausel auf bilden die äußere Schleife und die am weitesten rechts liegende Tabelle, um die innere Schleife zu bilden.

Also, je nachdem, wie die JOINs aufgebaut sind, kann es einen Unterschied in der Leistung geben.

SQLite versucht, diese automatisch zu optimieren, aber soweit ich die Dokumentation zu verstehen gibt es keine Garantie für den Erfolg (Highlights von mir):

jedoch SQLite werden Nest der Schleifen in einer anderen Reihenfolge, wenn dadurch so wird es helfen, bessere Indizes auszuwählen. [...] Join Neuordnung ist automatisch und in der Regel gut genug, dass Programmierer müssen nicht darüber nachdenken, vor allem, wenn ANALYZE verwendet wurde, um Statistiken über die verfügbaren Indizes zu sammeln. Aber gelegentlich werden einige Hinweise vom Programmierer benötigt.

2.) Beachten Sie auch, dass innere Joins intern in WHERE-Klauseln umgewandelt werden, so dass jede der Leistungsspitzen in der WHERE-Abschnitt des Dokuments könnte auch gelten:

Die ON und USING-Klauseln eines inneren Joins werden in zusätzliche Terme der WHERE-Klausel vor der WHERE-Klausel-Analyse , die oben in Paragraph 1.0 beschrieben ist, umgewandelt. Daher gibt es bei SQLite keinen Rechenvorteil, die neuere SQL92-Joinsyntax über die ältere SQL89-Kommasyntax zu verwenden.Beide enden genau das gleiche Ergebnis auf inneren Joins .

3.) Sie sollten erwägen, um weitere Spalten in der Anweisung auswählen, ob es irgendwelche Indizes auf ihnen:

Es ist für jede Spalte eines Index nicht notwendig ist, in einer WHERE erscheinen Klauselbegriff, damit dieser Index verwendet werden kann. Aber es kann nicht Lücken in den Spalten des Index verwendet werden.

+0

Alle Joins basieren auf Primärschlüsseln, ich denke, dass dies das Problem der Indizierung löst, aber ich versuche wirklich zu denken, ob 1 + 2 für meinen Fall Lebensretter sein könnte. – iCantSeeSharp

+0

Ich habe 'ANALYZE' vor meinem sql-Befehl verwendet und die Abfrage wurde ziemlich schnell ausgeführt. In Anbetracht der Tatsache, dass Sie die richtige Richtung für dieses spezielle Problem angegeben haben, erhalten Sie die Antwort. Vielen Dank! – iCantSeeSharp

3

Ich denke, dies geschieht aufgrund einer Art von SQLite und große Anzahl der Joins.

Versuchen Sie Datenbankschema zu reformieren, wie denormalize Daten für einen schnelleren Zugriff.

+0

Bedeutet "Natur of SQLite", dass die erwarteten Ergebnisse anders sind als die aktuell zurückgegebenen? – iCantSeeSharp

+0

@Souvlaki: Ich meine, dass SQLite eine gute Auslastung für eine solche Anzahl von Joins nicht unterstützt, auch haben Sie möglicherweise eine große Datei, was die resultierende Permanenz ebenfalls verschlechtert. – abatishchev

+0

Auch wenn die Abfrage auf Navicat ziemlich schnell ist? – iCantSeeSharp