Hat das Hinzufügen DISTINCT
im folgenden Beispiel Auswirkungen auf die Abfragelaufzeit?
Ist es ratsam, es manchmal als Hinweis zu verwenden?
SELECT *
FROM A
WHERE A.SomeColumn IN (SELECT DISTINCT B.SomeColumn FROM B)
Hat das Hinzufügen DISTINCT
im folgenden Beispiel Auswirkungen auf die Abfragelaufzeit?
Ist es ratsam, es manchmal als Hinweis zu verwenden?
SELECT *
FROM A
WHERE A.SomeColumn IN (SELECT DISTINCT B.SomeColumn FROM B)
Antworten:
Wenn Sie sich über solche Dinge wundern, sollten Sie die Ausführungspläne für Ihre Abfragen vergleichen.
Die Form des Ausführungsplans für Ihre Abfrage hängt natürlich davon ab, wie viele Zeilen Ihre Tabellen enthalten und welche Indizes definiert sind.
Ein Szenario, das zeigt, dass es keinen Leistungsunterschied gibt, besteht darin, dass wesentlich mehr Zeilen A
als Zeilen enthalten sind B
. Das Optimierungsprogramm wählt dann B
eine Verknüpfung in einer verschachtelten Schleife als Driving-Tabelle aus A
. Um ein korrektes Ergebnis zu erhalten, muss B
in beiden Abfragen ein Stream-Aggregat für die Tabelle verwendet werden, von dem nur die einzelnen Zeilen abgerufen werden B
. In diesem Fall hat das eindeutige Schlüsselwort also keinen Einfluss auf die Leistung.
Der Ausführungsplan für zwei andere offensichtliche zu testende Fälle, mehr Zeilen in B als A und die gleiche Anzahl von Zeilen in den Tabellen, zeigt auch den exakt gleichen Ausführungsplan für die Abfragen.
Aktualisieren
Vor der Abfrageoptimierung durchläuft die Abfrage eine Vereinfachungsphase. Mit dem Trace-Flag 8606 können Sie sehen, wie der logische Baum aussieht.
Der Eingabebaum für die Abfragen ist deutlich unterschiedlich, aber nach der Vereinfachung sind sie gleich.
Ref: Weitere undokumentierte Ablaufverfolgungsflags für das Abfrageoptimierungsprogramm und Deep Dive für das Abfrageoptimierungsprogramm - Teil 2
Eingabebaum und vereinfachter Baum für die Abfrage mit distinct:
*** Input Tree: ***
LogOp_Project QCOL: [xx].[dbo].[A].SomeColumn
LogOp_Select
LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002
ScaOp_SomeComp 2
ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
LogOp_GbAgg OUT(QCOL: [xx].[dbo].[B].SomeColumn,) BY(QCOL: [xx].[dbo].[B].SomeColumn,)
LogOp_Project
LogOp_Project
LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
AncOp_PrjList
*******************
*** Simplified Tree: ***
LogOp_LeftSemiJoin
LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002
LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
ScaOp_Identifier QCOL: [xx].[dbo].[B].SomeColumn
*******************
Eingabebaum und vereinfachter Baum für die Abfrage, die nicht distinct verwenden:
*** Input Tree: ***
LogOp_Project QCOL: [xx].[dbo].[A].SomeColumn
LogOp_Select
LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002
ScaOp_SomeComp 2
ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
LogOp_Project
LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006
AncOp_PrjList
AncOp_PrjList
*******************
*** Simplified Tree: ***
LogOp_LeftSemiJoin
LogOp_Get TBL: A A TableID=213679909 TableReferenceID=0 IsRow: COL: IsBaseRow1002
LogOp_Get TBL: B B TableID=229679966 TableReferenceID=0 IsRow: COL: IsBaseRow1006
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [xx].[dbo].[A].SomeColumn
ScaOp_Identifier QCOL: [xx].[dbo].[B].SomeColumn
*******************