Ich habe eine Abfrage, die ein paar Tabellen verknüpft und ziemlich schlechte Ergebnisse erzielt - Zeilenschätzungen sind weit entfernt (1000-mal), und der Join mit verschachtelten Schleifen wird ausgewählt, was zu mehreren Tabellensuchen führt. Die Form der Abfrage ist recht einfach und sieht ungefähr so aus:
SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id
WHERE t4.id = some_GUID
Als ich mit der Abfrage herumspielte, stellte ich fest, dass sie um ein Vielfaches schneller ausgeführt wird, wenn ich sie anspreche, einen Merge-Join für einen der Joins zu verwenden. Dies kann ich verstehen - Zusammenführen ist eine bessere Option für die Daten, die zusammengeführt werden, aber SQL Server schätzt es einfach nicht richtig, wenn die verschachtelten Schleifen ausgewählt werden.
Was ich nicht vollständig verstehe, ist, warum dieser Verknüpfungshinweis alle Schätzungen für alle Planoperatoren ändert? Beim Lesen verschiedener Artikel und Bücher bin ich davon ausgegangen, dass die Kardinalitätsschätzungen durchgeführt werden, bevor der Plan erstellt wird. Wenn Sie also einen Hinweis verwenden, werden die Schätzungen nicht geändert, sondern SQL Server wird ausdrücklich angewiesen, eine bestimmte physische Join-Implementierung zu verwenden.
Was ich jedoch sehe, ist, dass der Merge-Hinweis dazu führt, dass alle Schätzungen so ziemlich perfekt werden. Warum passiert dies und gibt es übliche Techniken, mit denen das Abfrageoptimierungsprogramm eine bessere Schätzung ohne einen Hinweis vornehmen kann - wenn man bedenkt, dass Statistiken dies offensichtlich zulassen?
UPD: anonymisierte Ausführungspläne finden Sie hier: https://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl=0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0
Ich habe die von beiden Abfragen verwendeten Statistiken mit TF 3604, 9292 und 9204 überprüft, und diese sind identisch. Gescannte / gesuchte Indizes unterscheiden sich jedoch zwischen den Abfragen.
Außerdem habe ich versucht, die Abfrage mit OPTION (FORCE ORDER)
auszuführen - sie läuft sogar noch schneller als der Merge-Join und wählt für jeden Join HASH MATCH.