Was ist der interne Algorithmus für die Funktionsweise des Operators Except in SQL Server? Nimmt es intern einen Hash jeder Zeile und vergleicht es?
David Lozinksi führte eine Studie durch, SQL: Der schnellste Weg, neue Datensätze einzufügen, wo noch keiner existiert. Er zeigte, dass die Except-Anweisung für Zeilen mit großer Anzahl die schnellste ist. eng mit unseren Ergebnissen unten verbunden.
Annahme: Ich würde denken, dass der Link-Join am schnellsten ist, da er nur eine Spalte vergleicht. Außer würde am längsten dauern, da alle Spalten verglichen werden müssen.
Mit diesen Ergebnissen ist unser Denken jetzt Außer automatisch und nimmt intern einen Hash von jeder Zeile? Ich habe mir einen Ausführungsplan angesehen und er verwendet etwas Hash.
Hintergrund: Unser Team hat zwei Heap-Tabellen verglichen. Tabelle A Zeilen, die nicht in Tabelle B enthalten sind, wurden in Tabelle B eingefügt.
Die Heap-Tabellen (aus dem alten Textdateisystem) haben keine Primärschlüssel / Guids / Bezeichner. Einige der Tabellen hatten doppelte Zeilen, daher haben wir den Hash jeder Zeile gefunden, doppelte Zeilen entfernt und Primärschlüssel-IDs erstellt.
1) Zuerst haben wir eine Ausnahme-Anweisung ausgeführt, ohne (Hash-Spalte)
select * from TableA
Except
Select * from TableB,
2) Dann haben wir einen Link-Join-Vergleich zwischen den beiden Tabellen auf der HashRowId durchgeführt
select *
FROM dbo.TableA A
left join dbo.TableB B
on A.RowHash = B.RowHash
where B.Hash is null
überraschenderweise war der Insert Statement Exert der schnellste.
Die Ergebnisse entsprechen tatsächlich den Testergebnissen von David Lozinksi
quelle
Antworten:
Ich würde nicht sagen, dass es einen speziellen internen Algorithmus für gibt
EXCEPT
. FürA EXCEPT B
nimmt der Motor unterschiedliche Tupel aus A und Subtraktionen Zeilen (falls erforderlich) , dass Spiel in B. Es gibt keinen speziellen Abfrage - Plan - Betreiber. Die Unterscheidung und die Subtraktion werden durch die typischen Operatoren implementiert, die Sie mit einer Sortierung oder einem Join sehen würden. Nested-Loop-Join, Merge-Join und Hash-Join werden unterstützt. Um dies zu zeigen, werfe ich 15 Millionen Zeilen in ein Paar Haufen:Das Optimierungsprogramm trifft die üblichen kostenbasierten Entscheidungen zur Implementierung der Sortierung und des Joins. Mit zwei Haufen bekomme ich wie erwartet einen Hash-Join. Sie können andere Verknüpfungstypen natürlich anzeigen, indem Sie Indizes hinzufügen oder die Daten in einer der beiden Tabellen ändern. Im Folgenden erzwinge ich Merge- und Loop-Verknüpfungen mit Hinweisen nur zur Veranschaulichung:
Nein, es wird wie jeder andere Join implementiert. Ein Unterschied besteht darin, dass NULL-Werte als gleich behandelt werden. Dies ist eine spezielle Art von Vergleich, die Sie im Ausführungsplan sehen können :
<Compare CompareOp="IS">
. Mit T-SQL können Sie jedoch denselben Plan erhalten, der dasEXCEPT
Schlüsselwort nicht enthält . Das Folgende hat beispielsweise genau den gleichen Abfrageplan wie dieEXCEPT
Abfrage, die einen Hash-Join verwendet:Wenn Sie das XML der Ausführungspläne unterscheiden, werden nur oberflächliche Unterschiede in Bezug auf Aliase und ähnliches angezeigt. Die Testreste für die Hash-Joins führen den Zeilenvergleich durch. Sie sind für beide Abfragen gleich:
Wenn Sie immer noch Zweifel haben, habe ich PerfView mit der höchsten verfügbaren Abtastrate ausgeführt, um Anrufstapel für die Abfrage mit
EXCEPT
und die Abfrage ohne zu erhalten. Hier sind die Ergebnisse nebeneinander:Es gibt keinen wirklichen Unterschied. Die Call-Stacks dort sind aufgrund der Hash-Übereinstimmungen im Plan vorhanden. Wenn ich Indizes hinzufüge, um einen natürlichen Zusammenführungs-Join zu erhalten, werden in den Aufrufstapeln keine Verweise auf Hashing angezeigt:
Jedes auftretende Hashing ist auf die Implementierung von Hash-Match-Operatoren zurückzuführen. Es gibt nichts Besonderes,
EXCEPT
was zu einem speziellen internen Hashing-Vergleich führt.quelle