Ich habe bemerkt, dass Datenbankabfragen beim Hinzufügen von .ToArray () oder .ToList () zu Abfragen schneller ausgeführt werden. Liegt dies daran, dass der Datensatz in den Arbeitsspeicher geladen wird und alle nachfolgenden Abfragen im Arbeitsspeicher ausgeführt werden, anstatt weitere teure Datenbankaufrufe durchzuführen?
Was sollte die Grenze für In-Memory-Speicher für Datenbankabfragen sein, da ich befürchte, dass zu viel interner Speicher das gesamte Projekt verlangsamen wird, da ich sicher bin, dass die Aufnahme von zu viel Arbeitsspeicher die Geschwindigkeit verlangsamen kann dramatisch runter.
EDIT: Dies ist für Linq-SQL-Abfragen. Ich verwende SQL Server 2008.
Beispiel 1: Ausführen einer großen Datenbankabfrage und In-Memory-Filterung
Ich habe eine Datenbanktabelle mit 5 000 Zeilen. Ich frage die gesamte Tabelle ab (z. B. SELECT * From Clients). Meine nächsten paar Abfragen basieren auf Feldern aus der vorherigen Abfrage: a) Bekommen Sie alle männlichen Klienten; b) Erhalte alle weiblichen Klienten c) Erhalte alle Klienten, wo Vorname mit A beginnt.
Beispiel 2: Ausführen häufigerer Datenbankaufrufe
Unter Verwendung derselben Client-Tabelle mit 5000 Zeilen muss ich 3 Abfragen durchführen a) Alle männlichen Clients abrufen; b) Holen Sie sich alle weiblichen Clients c) Holen Sie sich alle Clients, deren Vorname mit A beginnt. Ich mache alle Abfragen über Datenbankaufrufe und nicht im Speicher.
Welche Methode ist effizienter?
HINWEIS: Ich habe bei meinen Abfragen ein Entitätsframework "context" verwendet. Die Antwort gilt jedoch für Entity Framework oder LINQ-to-SQL.
ToArray () und ToList () werden niemals eine Abfrage beschleunigen. Sie können es jedoch so aussehen lassen, wenn Sie die Abfrage versehentlich mehrmals ausführen. Dies ist ein häufiger Fehler bei der Verwendung von LINQ. Zum Beispiel:
%Vor%Die obige Zeile fragt NICHT die Datenbank nach süßen Welpen ab. Stattdessen wird eine Abfrage erstellt, die zu einem späteren Zeitpunkt nach den Welpen fragt. Dies wird als verzögerte Ausführung bezeichnet. Quizfrage: Welcher Typ ist "Daten" im obigen Beispiel?
Die Abfrage wird tatsächlich ausgeführt, wenn Sie die Variablendaten aufzählen. Diese Variable ist vom Typ IEnumerable. IEnumerables unterscheiden sich von Listen oder Arrays. Ein IEnumerable ist lediglich ein Versprechen, dass die Daten erhalten werden können. Es bedeutet nicht, dass Sie tatsächlich die Daten haben.
%Vor%Der obige foreach-Aufruf erzwingt die Ausführung der Abfrage. Die Welpen werden auf den Bildschirm gehen, aber sie werden nicht irgendwo in einem Array oder einer Liste zwischengespeichert. Also jetzt, wenn Sie das tun:
%Vor%Dieser Foreach bewirkt, dass die Abfrage erneut ausführt . In der Tat, wenn neue Welpen in der Datenbank zwischen den beiden Aufrufen hinzugefügt oder entfernt wurden, könnten Sie sogar andere Ergebnisse erhalten! Angenommen, wir haben stattdessen ToList () zum ersten Aufruf hinzugefügt.
%Vor%Daten sind jetzt vom Typ Liste. Unter der Haube erzeugt dies ein IEnumerable, macht dann eine foreach durch und legt die Ergebnisse in eine Liste. Wenn Sie nun den Namen und den Besitzer des Welpen anzeigen, wird die Datenbank nicht zweimal abgefragt. Stattdessen durchläuft es die Liste zweimal.
Wenn Sie nach der verzögerten Ausführung suchen, finden Sie viele interessante Anwendungen dafür, sowie Vorbehalte wie die, die ich aufgelistet habe. Im Allgemeinen möchten Sie sicherstellen, dass Sie Ihre Abfrage nur einmal ausführen. Wenn das eine ToList () erfordert, dann ist das großartig. Aber fügen Sie ToList () nicht unnötig hinzu. Verwenden Sie ein letztes Beispiel:
%Vor%Sollten Sie die ToList () hier haben? Nein! Denn das würde den Aufwand einer Liste erhöhen, wenn Sie die Liste wirklich nicht benötigen. Noch schlimmer:
%Vor%Das ist noch schlimmer! Es zog alle Welpen in eine Liste in Erinnerung und zählte sie dann. Aber diese Abfrage erfordert nie einmal, die Welpen überhaupt zu packen. Auf diese Weise:
%Vor%Es teilt dem SQL-Server mit, die Anzahl der Welpen zu zählen, und verschwendet niemals Bandbreite oder Speicher, um die Welpen tatsächlich aus der Datenbank zu laden oder sie an C # oder irgendetwas davon zu senden.
Ich hoffe, das hilft!
Tags und Links c# linq performance toarray