SQL Server 2008 R2-Abfrageoptimierungspuzzlespiel
Wir haben zwei Tabellen mit jeweils 9 Millionen Zeilen. 70.000 Zeilen sind unterschiedlich, die anderen sind gleich.
Das ist schnell, 13 Sekunden,
select * from bigtable1
except select * from similar_bigtable2
Dies sortiert die Ausgabe und ist auch schnell, auch 13 Sekunden,
select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column
Das ist zwar enorm langsam:
;with q as (
select * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
Und selbst ein "Trick", den ich manchmal verwende, um SQL Server darauf hinzuweisen, dass er einen bestimmten Teil der Abfrage vorab berechnen muss, funktioniert nicht und führt auch zu langsamen Abfragen:
;with q as (
select top 100 percent * from bigtable1
except select * from similar_bigtable2
)
select * from q order by sort_column
In den Abfrageplänen ist der Grund nicht schwer zu finden:
SQL Server platziert zwei Arten von 9 Millionen Zeilen vor dem Hashmatch, während ich es vorziehen würde, nur eine Art von 70.000 Zeilen nach dem Hashmatch hinzuzufügen.
Also die Frage: Wie kann ich das Abfrageoptimierungsprogramm dazu anweisen?
EXCEPT
(zB OUTER JOIN
) ausprobiert ? Mir ist klar, dass die Syntax weniger praktisch ist, aber Sie können dort möglicherweise besser mit Index- / Verknüpfungshinweisen spielen (oder müssen dies nicht). Die Alternative, die Sie jetzt verwenden (Zeug zuerst in eine #temp-Tabelle), ist eine Umgehung des letzten Auswegs, aber in einigen Fällen ist es die einzige Möglichkeit, das Optimierungsprogramm zu zwingen, zwei Teile einer Abfrage auf die von Ihnen gewünschte Weise vollständig zu trennen.