Ich verwende System.Data.SQLite
und SQLiteDataReader
in meinem C # -Projekt. Ich bin mit Leistungsproblemen konfrontiert, wenn ich die Ergebnisse einer Abfrage mit angehängten Datenbanken erhalte.
Hier ist ein Beispiel für eine Abfrage zum Suchen von Text in zwei Datenbanken:
%Vor%Wenn diese Abfrage mit SQLiteStudio oder SQLiteAdmin ausgeführt wird, funktioniert das einwandfrei. Ich erhalte die Ergebnisse in ein paar Sekunden (die Record-Tabelle kann hunderttausende Datensätze enthalten, die Abfrage gibt 36000 Datensätze zurück).
Wenn diese Abfrage in meinem C # -Projekt ausgeführt wird, dauert die Ausführung einige Sekunden, aber es dauert Stunden, bis alle Ergebnisse durchlaufen sind.
Hier ist mein Code:
%Vor% Der Aufruf der Methode Read
von SQLiteDataReader
kann mehr als 10 Sekunden dauern! Ich nehme an, das liegt daran, dass SQLiteDataReader
lazy geladen ist (und so gibt es nicht das ganze Rowset zurück, bevor die Ergebnisse gelesen werden), habe ich recht?
Ich weiß nicht, ob das etwas mit Lazy Loading zu tun hat, wie ich anfangs gesagt habe, aber alles was ich will, ist ALLE Ergebnisse zu bekommen, sobald die Abfrage beendet ist. Ist das nicht möglich? Meiner Meinung nach ist das wirklich seltsam, dass es Stunden dauert, um Ergebnisse einer Anfrage in wenigen Sekunden zu erhalten ...
Ich habe gerade eine COUNT(*)
in meine Select-Abfrage eingefügt, um zu sehen, ob ich die Gesamtanzahl der Ergebnisse bei der ersten data.Read()
erhalten konnte, nur um sicher zu sein, dass nur die Iteration der Ergebnisse stattfand so lange. Und ich lag falsch: Diese neue Anfrage wird in wenigen Sekunden in SQLiteAdmin / SQLiteStudio ausgeführt, benötigt aber Stunden, um in meinem C # -Projekt ausgeführt zu werden. Irgendeine Idee, warum die gleiche Abfrage in meinem C # -Projekt so viel länger auszuführen ist?
Dank EXPLAIN QUERY PLAN
ist mir aufgefallen, dass es im Ausführungsplan für dieselbe Abfrage zwischen SQLiteAdmin / SQLiteStudio und meinem C # -Projekt einen kleinen Unterschied gab. Im zweiten Fall verwendet es AUTOMATIC PARTIAL COVERING INDEX
für DB2Record, anstatt den Primärschlüsselindex zu verwenden. Gibt es eine Möglichkeit, die Verwendung von automatischen Teilabdeckungsindizes zu ignorieren / zu deaktivieren? Ich weiß, dass es verwendet wird, um die Abfragen zu beschleunigen, aber in meinem Fall ist es eher das Gegenteil, das passiert ...
Danke.
Neben übereinstimmenden Datensätzen scheint es auch zu sein, wie oft die Strings übereinstimmen. Das Ergebnis dieser Zählung wird auch in der WHERE
-Klausel verwendet.
Sie möchten die Anzahl der Übereinstimmungen, aber die Anzahl der Übereinstimmungen spielt in der WHERE
-Klausel keine Rolle - Sie könnten versuchen, die WHERE
-Klausel zu ändern:
Es kann jedoch nicht zu einem Unterschied kommen - vor allem, wenn es keinen Index für die Value
Spalten gibt - aber einen Versuch wert. Indizes in Textspalten erfordern viel Platz, also würde ich das nicht blind empfehlen.
Wenn Sie dies noch nicht getan haben, platzieren Sie einen Index für die Spalte RecordID
des DB2.
Sie können EXPLAIN QUERY PLAN SELECT ...
verwenden, damit SQLite ausspuckt, was es versucht, um Ihre Abfrage durchzuführen. Die Ausgabe könnte helfen, das Problem zu diagnostizieren.
Ein weiterer Grund, warum die SQL-Abfrage bei der Ausführung mit ADO.NET und dem nativen Dienstprogramm (wie SQLiteAdmin) unterschiedlich lange dauern kann, sind die in CommandText verwendeten Befehlsparameter (aus dem Code ist nicht ersichtlich, ob Parameter verwendet werden oder nicht) ). Abhängig von der ADO.NET-Anbieterimplementierung werden die folgenden identischen CommandText-Werte verwendet:
%Vor%und
%Vor%kann zu absolut unterschiedlichen Ausführungsplan- und Abfrageleistung führen.
Ein anderer Vorschlag: Sie können das Journal (Angabe von "Journal Mode = off;" in der Verbindungszeichenfolge) und den synchronen Modus ("Synchronous = off;") deaktivieren, da diese Optionen in einigen Fällen auch die Abfrageleistung beeinflussen können.
Tags und Links c# sqlite performance system.data.sqlite datareader