LINQ ToList (). Take (10) vs. Take (10) .ToList () was eine effizientere Abfrage generiert

7

Angesichts der folgenden LINQ-Erklärung (en), die effizienter sein wird?

Eins:

%Vor%

ZWEI:

%Vor%

Ich bin mir bewusst, dass .ToList () die Abfrage sofort ausführt.

    
Mani 08.12.2010, 16:36
quelle

5 Antworten

17
___ answer4389909 ___

Die zweite Version wird effizienter sein (sowohl bei der Zeit als auch bei der Speichernutzung). Angenommen, Sie haben eine Sequenz mit 1.000.000 Elementen:

  1. Die erste Version durchläuft alle 1.000.000 Elemente und fügt sie zu einer Liste hinzu. Dann, schließlich, werden die ersten 10 Elemente aus dieser großen Liste genommen.

  2. Die zweite Version muss nur die ersten 10 Elemente durchlaufen und sie zu einer Liste hinzufügen. (Die restlichen 999.990 Artikel müssen nicht einmal berücksichtigt werden.)

___ answer8474249 ___

Wie wäre es damit?

%Vor%

Version 1:

%Vor%

das dauerte: 20 sec auf dem Server

Version 2:

%Vor%

dies dauerte: 1 sec auf dem Server

Was denkst du jetzt? Irgendeine Idee warum?

    
___ answer4389928 ___

Die zweite Option.

Der erste wird die gesamte Aufzählung bewerten und in eine List () gleiten; dann richten Sie den Iterator ein, der die ersten zehn Objekte durchlaufen und dann beenden wird.

Der zweite richtet zuerst den Take () - Iterator ein, also was immer später passiert, es werden nur 10 Objekte ausgewertet und an die "Downstream" -Verarbeitung gesendet (in diesem Fall die ToList (), die diese zehn Elemente und gebe sie als die konkrete Liste zurück).

    
___ tag123c ___ C # (sprich "Cis") ist eine objektorientierte Programmiersprache auf hohem Niveau, die für die Erstellung einer Vielzahl von Anwendungen entwickelt wurde, die auf dem .NET Framework (oder .NET Core) ausgeführt werden. C # ist einfach, leistungsfähig, typsicher und objektorientiert. ___ tag123linq ___ Die Language Integrated Query (LINQ) ist eine Microsoft .NET Framework-Komponente, die native Datenabfragefunktionen zu .NET-Sprachen hinzufügt. Bitte denken Sie bei Bedarf daran, ausführlichere Tags zu verwenden, zum Beispiel [linq-to-sql], [linq-to-entities] / [entity-framework] oder [plinq] ___ tag123linqtosql ___ LINQ to SQL ist eine Komponente von .NET Framework Version 3.5, die eine Laufzeitinfrastruktur für die Verwaltung relationaler Daten als Objekte in Microsoft SQL Server bereitstellt. ___ qstntxt ___

Angesichts der folgenden LINQ-Erklärung (en), die effizienter sein wird?

Eins:

%Vor%

ZWEI:

%Vor%

Ich bin mir bewusst, dass .ToList () die Abfrage sofort ausführt.

    
___ qstnhdr ___ LINQ ToList (). Take (10) vs. Take (10) .ToList () was eine effizientere Abfrage generiert ___ antwort4389913 ___

Ihre erste Option wird nicht funktionieren, weil Take sie in IEnumerable<T> konvertiert. Ihr Rückgabetyp ist List<T> , also müssten Sie Take(10) machen, was ineffizienter ist.

Indem Sie Queryable.ToList() ausführen, erzwingen Sie, dass Enumerable.ToList() LINQ für Objekte ist, während der andere Filter den Filter an die Datenbank oder andere zugrunde liegende Datenquellen weitergibt. Mit anderen Worten, wenn Sie zuerst ToList ausführen, müssen ALLE Objekte aus der Datenbank übertragen und im Speicher zugeordnet werden. Dann filtern Sie auf die ersten 10. Wenn Sie von Millionen von Datenbankzeilen (und Objekten) sprechen, können Sie sich vorstellen, dass dies SEHR ineffizient und nicht skalierbar ist.

Der zweite wird auch sofort ausgeführt, weil Sie Take haben, also kein Unterschied.

    
___ antwort4389904 ___

Die erste Version würde nicht einmal kompilieren - denn der Rückgabewert von OrderBy ist ein %code% , nicht ein %code% . Du brauchst es also:

%Vor%

Das würde alle Daten aus der Datenbank holen und in eine Liste konvertieren, dann die ersten 10 Einträge nehmen, dann sie wieder in eine Liste konvertieren.

Das %code% in der Datenbank erscheinen zu lassen (d. h. die zweite Form) sieht für mich viel billiger aus ...

Beachten Sie, dass es keine Methode %code% gibt - Sie rufen am Ende %code% auf, die alle Einträge abruft. Mit anderen Worten, der Aufruf von %code% nimmt nicht an der SQL-Übersetzung teil, während %code% dies tut.

Beachten Sie auch, dass die Verwendung eines Abfrageausdrucks auch hier keinen Sinn ergibt. Ich würde es schreiben als:

%Vor%

Bitte beachten Sie, dass Sie vielleicht einen %code% -Aufruf haben möchten - ansonsten werden nur die ersten 10 gefundenen Einträge benötigt, die nicht die neuesten sind ...

    
___
Jon Skeet 08.12.2010, 16:39
quelle
2
___ answer4389909 ___

Die zweite Version wird effizienter sein (sowohl bei der Zeit als auch bei der Speichernutzung). Angenommen, Sie haben eine Sequenz mit 1.000.000 Elementen:

  1. Die erste Version durchläuft alle 1.000.000 Elemente und fügt sie zu einer Liste hinzu. Dann, schließlich, werden die ersten 10 Elemente aus dieser großen Liste genommen.

  2. Die zweite Version muss nur die ersten 10 Elemente durchlaufen und sie zu einer Liste hinzufügen. (Die restlichen 999.990 Artikel müssen nicht einmal berücksichtigt werden.)

___ answer8474249 ___

Wie wäre es damit?

%Vor%

Version 1:

%Vor%

das dauerte: 20 sec auf dem Server

Version 2:

%Vor%

dies dauerte: 1 sec auf dem Server

Was denkst du jetzt? Irgendeine Idee warum?

    
___ answer4389928 ___

Die zweite Option.

Der erste wird die gesamte Aufzählung bewerten und in eine List () gleiten; dann richten Sie den Iterator ein, der die ersten zehn Objekte durchlaufen und dann beenden wird.

Der zweite richtet zuerst den Take () - Iterator ein, also was immer später passiert, es werden nur 10 Objekte ausgewertet und an die "Downstream" -Verarbeitung gesendet (in diesem Fall die ToList (), die diese zehn Elemente und gebe sie als die konkrete Liste zurück).

    
___ tag123c ___ C # (sprich "Cis") ist eine objektorientierte Programmiersprache auf hohem Niveau, die für die Erstellung einer Vielzahl von Anwendungen entwickelt wurde, die auf dem .NET Framework (oder .NET Core) ausgeführt werden. C # ist einfach, leistungsfähig, typsicher und objektorientiert. ___ tag123linq ___ Die Language Integrated Query (LINQ) ist eine Microsoft .NET Framework-Komponente, die native Datenabfragefunktionen zu .NET-Sprachen hinzufügt. Bitte denken Sie bei Bedarf daran, ausführlichere Tags zu verwenden, zum Beispiel [linq-to-sql], [linq-to-entities] / [entity-framework] oder [plinq] ___ tag123linqtosql ___ LINQ to SQL ist eine Komponente von .NET Framework Version 3.5, die eine Laufzeitinfrastruktur für die Verwaltung relationaler Daten als Objekte in Microsoft SQL Server bereitstellt. ___ qstntxt ___

Angesichts der folgenden LINQ-Erklärung (en), die effizienter sein wird?

Eins:

%Vor%

ZWEI:

%Vor%

Ich bin mir bewusst, dass .ToList () die Abfrage sofort ausführt.

    
___ qstnhdr ___ LINQ ToList (). Take (10) vs. Take (10) .ToList () was eine effizientere Abfrage generiert ___ antwort4389913 ___

Ihre erste Option wird nicht funktionieren, weil .Take(10) sie in IEnumerable<Log> konvertiert. Ihr Rückgabetyp ist List<Log> , also müssten Sie return logEntries.ToList().Take(10).ToList() machen, was ineffizienter ist.

Indem Sie .ToList().Take(10) ausführen, erzwingen Sie, dass .Take(10) LINQ für Objekte ist, während der andere Filter den Filter an die Datenbank oder andere zugrunde liegende Datenquellen weitergibt. Mit anderen Worten, wenn Sie zuerst .ToList() ausführen, müssen ALLE Objekte aus der Datenbank übertragen und im Speicher zugeordnet werden. Dann filtern Sie auf die ersten 10. Wenn Sie von Millionen von Datenbankzeilen (und Objekten) sprechen, können Sie sich vorstellen, dass dies SEHR ineffizient und nicht skalierbar ist.

Der zweite wird auch sofort ausgeführt, weil Sie .ToList() haben, also kein Unterschied.

    
___ antwort4389904 ___

Die erste Version würde nicht einmal kompilieren - denn der Rückgabewert von %code% ist ein %code% , nicht ein %code% . Du brauchst es also:

%Vor%

Das würde alle Daten aus der Datenbank holen und in eine Liste konvertieren, dann die ersten 10 Einträge nehmen, dann sie wieder in eine Liste konvertieren.

Das %code% in der Datenbank erscheinen zu lassen (d. h. die zweite Form) sieht für mich viel billiger aus ...

Beachten Sie, dass es keine Methode %code% gibt - Sie rufen am Ende %code% auf, die alle Einträge abruft. Mit anderen Worten, der Aufruf von %code% nimmt nicht an der SQL-Übersetzung teil, während %code% dies tut.

Beachten Sie auch, dass die Verwendung eines Abfrageausdrucks auch hier keinen Sinn ergibt. Ich würde es schreiben als:

%Vor%

Bitte beachten Sie, dass Sie vielleicht einen %code% -Aufruf haben möchten - ansonsten werden nur die ersten 10 gefundenen Einträge benötigt, die nicht die neuesten sind ...

    
___
Nelson Rothermel 08.12.2010 16:40
quelle
2

Die zweite Version wird effizienter sein (sowohl bei der Zeit als auch bei der Speichernutzung). Angenommen, Sie haben eine Sequenz mit 1.000.000 Elementen:

  1. Die erste Version durchläuft alle 1.000.000 Elemente und fügt sie zu einer Liste hinzu. Dann, schließlich, werden die ersten 10 Elemente aus dieser großen Liste genommen.

  2. Die zweite Version muss nur die ersten 10 Elemente durchlaufen und sie zu einer Liste hinzufügen. (Die restlichen 999.990 Artikel müssen nicht einmal berücksichtigt werden.)

LukeH 08.12.2010 16:40
quelle
1

Wie wäre es damit?

%Vor%

Version 1:

%Vor%

das dauerte: 20 sec auf dem Server

Version 2:

%Vor%

dies dauerte: 1 sec auf dem Server

Was denkst du jetzt? Irgendeine Idee warum?

    
Morpheus 12.12.2011 12:22
quelle
0

Die zweite Option.

Der erste wird die gesamte Aufzählung bewerten und in eine List () gleiten; dann richten Sie den Iterator ein, der die ersten zehn Objekte durchlaufen und dann beenden wird.

Der zweite richtet zuerst den Take () - Iterator ein, also was immer später passiert, es werden nur 10 Objekte ausgewertet und an die "Downstream" -Verarbeitung gesendet (in diesem Fall die ToList (), die diese zehn Elemente und gebe sie als die konkrete Liste zurück).

    
KeithS 08.12.2010 16:41
quelle

Tags und Links