Ist die Reihenfolge des Prädikats bei der Verwendung von LINQ wichtig?

8

Ich verstehe, dass das Ausführen von Operationen in verschiedenen Ordnungen eine andere Leistung ergibt, wie zum Beispiel den Unterschied zwischen der folgenden langsamen Abfrage:

%Vor%

und dieses schnellere:

%Vor%

Aber das ist nicht meine Frage:

Meine Frage bezieht sich auf die Ausführung des Kurzschlusses in Bezug auf ein LINQ-Prädikat. Wenn ich eine Where-Klausel verwende, wie in diesem Fall:

%Vor%

Ist die Reihenfolge der Argumente nicht wichtig? Zum Beispiel würde ich erwarten, dass die Ausführung einer .Equals-Abfrage insgesamt zu einer langsameren Abfrage führt, da die Item1 == 12 Integer-Auswertung eine viel schnellere Operation ist.

Wenn Ordnung wichtig ist, wie wichtig ist das? Natürlich ist das Aufrufen von Methoden wie .Equals wahrscheinlich eine viel größere Verlangsamung, als wenn ich nur ein paar ganze Zahlen vergleichen würde, aber ist das eine relativ kleine Leistungseinbuße im Vergleich zu der, wie langsam 'LINQ funktioniert? Da LINQ eine Menge Methodenaufrufe macht, ist etwas wie .Equals wirklich wichtig, da es - außer wenn es überschrieben wird - nativen Frameworkcode ausführt, richtig? Auf der anderen Seite wird eine Standard-MSIL-Methode deutlich langsamer sein?

Gibt es noch weitere Compiler-Optimierungen bei dieser Abfrage, die dies möglicherweise unter der Haube beschleunigen?

Danke für die Gedanken und Klarstellungen! Brett

    
Brett 24.02.2012, 19:07
quelle

1 Antwort

13

Die Antwort wird für verschiedene LINQ-Anbieter anders sein. Insbesondere ist die Geschichte für LINQ zu Objekten sehr unterschiedlich und sagt LINQ zu Entitäten.

In LINQ to Objects akzeptiert der Where-Operator den Filter als Func & lt; TSource, bool & gt ;. Func & lt; & gt; ist ein Delegat, also können Sie sich im Rahmen dieser Diskussion einen Funktionszeiger vorstellen. In LINQ to Objects entspricht Ihre Abfrage:

%Vor%

Das Wichtigste ist, dass MyFilter eine normale C # -Methode ist und daher normale C # -Regeln gelten, einschließlich des Kurzschlussverhaltens von & amp; & amp; Folglich werden die Bedingungen in der Reihenfolge ausgewertet, in der Sie sie geschrieben haben. LINQ to Objects kann MyFilter für verschiedene Eingabeelemente aufrufen, aber MyFilter kann nicht geändert werden.

In LINQ to Entities und LINQ to SQL akzeptiert der Where-Operator den Filter als Expression & lt; Func & lt; TSource, bool & gt; & gt; & gt; . Jetzt wird der Filter in den Where-Operator als Datenstruktur übergeben, die den Ausdruck beschreibt. In diesem Fall wird der LINQ-Anbieter die Datenstruktur (die "Ausdrucksbaumstruktur") betrachten, und es ist Sache des LINQ-Anbieters, zu entscheiden, wie er interpretiert werden soll.

In LINQ to Entities- und LINQ to SQL-Fällen wird der Ausdrucksbaum in SQL übersetzt. Und dann ist es Aufgabe des Datenbankservers, zu entscheiden, wie die Abfrage ausgeführt wird. Der Server darf die Bedingungen definitiv neu anordnen, und es können noch substantiellere Optimierungen vorgenommen werden. Wenn die SQL-Tabelle beispielsweise einen Index für eine der Spalten enthält, auf die in der Bedingung verwiesen wird, kann der Server auswählen, den Index zu verwenden, und sogar Zeilen vermeiden, die nicht mit diesem bestimmten Bedingungsteil übereinstimmen.

    
Igor ostrovsky 24.02.2012, 21:15
quelle