Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Warum ist dies ein Index Scan und kein Index Seek?

Es verwendet hauptsächlich einen Index Scan, weil es auch einen Merge Join verwendet. Der Merge Join-Operator erfordert zwei Eingabestreams, die beide in einer Reihenfolge sortiert sind, die mit den Join-Bedingungen kompatibel ist.

Und es verwendet den Merge Join-Operator, um Ihren INNER JOIN zu realisieren, weil es glaubt, dass dies schneller sein wird als der typischere Nested Loop Join-Operator. Und es ist wahrscheinlich richtig (das ist es normalerweise), indem es die beiden von ihm gewählten Indizes verwendet, hat es Eingabeströme, die beide gemäß Ihrer Join-Bedingung (LocationID) vorsortiert sind. Wenn die Eingabeströme so vorsortiert sind, dann sind Merge Joins fast immer schneller als die anderen beiden (Loop und Hash Joins).

Der Nachteil ist, was Sie bemerkt haben:Es scheint, als würde der gesamte Index gescannt. Wie kann das also schneller sein, wenn so viele Datensätze gelesen werden, die möglicherweise nie verwendet werden? Die Antwort ist, dass Scans (aufgrund ihrer sequentiellen Natur) 10- bis 100-mal so viele Datensätze pro Sekunde lesen können wie Suchvorgänge.

Jetzt gewinnen Suchvorgänge normalerweise, weil sie selektiv sind:Sie erhalten nur die Zeilen, nach denen Sie fragen, während Scans nicht selektiv sind:Sie müssen jede Zeile im Bereich zurückgeben. Aber weil Scans viel haben Durch eine höhere Leserate können sie Suchvorgänge häufig schlagen, solange das Verhältnis von verworfenen Zeilen zu übereinstimmenden Zeilen niedriger ist als das Verhältnis von Scanzeilen/Sek. vs. Suchzeilen/Sek.

Fragen?

OK, ich wurde gebeten, den letzten Satz näher zu erläutern:

Eine "verworfene Zeile" ist eine, die der Scan liest (weil er alles im Index lesen muss), die aber vom Merge Join-Operator abgelehnt wird, weil sie keine Übereinstimmung auf der anderen Seite hat, möglicherweise weil die Die Bedingung der WHERE-Klausel hat sie bereits ausgeschlossen.

"Übereinstimmende Zeilen" sind diejenigen, die gelesen werden und die tatsächlich mit etwas im Merge Join übereinstimmen. Dies sind dieselben Zeilen, die von einem Seek gelesen worden wären, wenn der Scan durch einen Seek ersetzt worden wäre.

Sie können herausfinden, was vorhanden ist, indem Sie sich die Statistiken im Abfrageplan ansehen. Sehen Sie den riesigen dicken Pfeil links neben dem Index-Scan? Das stellt dar, wie viele Zeilen der Optimierer denkt, dass er mit dem Scan lesen wird. Das Statistikfeld des von Ihnen geposteten Index-Scans zeigt, dass die tatsächlich zurückgegebenen Zeilen etwa 5,4 Millionen (5.394.402) betragen. Dies ist gleich:

TotalScanRows = (MatchingRows + DiscardedRows)

(In meinen Begriffen jedenfalls). Um die übereinstimmenden Zeilen zu erhalten, sehen Sie sich die vom Merge Join-Operator gemeldeten "Tatsächlichen Zeilen" an (möglicherweise müssen Sie die TOP 100 entfernen, um dies genau zu erhalten). Sobald Sie dies wissen, können Sie die verworfenen Zeilen wie folgt abrufen:

DiscardedRows = (TotalScanRows - MatchingRows)

Und jetzt können Sie das Verhältnis berechnen.