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.
quelle
Antworten:
Nicht genau. Eine anfängliche Kardinalitätsschätzung wird abgeleitet (nach Vereinfachungen und anderen Arbeiten), die die vom Optimierer gewählte anfängliche Verknüpfungsreihenfolge beeinflusst.
Nachfolgende Untersuchungen (während der kostenbasierten Optimierung) können jedoch häufig dazu führen, dass neue Kardinalitätsschätzungen berechnet werden. Diese späteren CEs können mehr oder weniger genau sein. Wenn sich eine Unterschätzung ergibt, wählt das Optimierungsprogramm möglicherweise einen Plan, der billiger aussieht, aber tatsächlich viel länger ausgeführt wird.
Im Allgemeinen gibt es keine Garantie dafür, dass Kardinalitätsschätzungen für semantisch identische Teilbäume zu denselben Ergebnissen führen. Immerhin handelt es sich um einen statistischen Prozess, und einige Vorgänge werden von CE besser unterstützt als andere.
In Ihrem Fall scheint es einen anderen Faktor zu geben: Der Optimierer führt einen Top ein (oder verschiebt ihn), wodurch ein Zeilenziel für den untergeordneten Baum festgelegt wird:
Wenn Sie das Ablaufverfolgungsflag 4138 (auf 2008 R2 oder höher) aktivieren, stimmen die Schätzungen möglicherweise besser mit den Erwartungen überein, oder sogar, dass das Optimierungsprogramm keine verschachtelten Schleifen mehr auswählt.
Hier steckt ein bisschen Glück. Die Leute neigen dazu, Abfragen oder zumindest die Verknüpfungen in der Reihenfolge zu schreiben, in der sie erwarten, dass sie physisch ausgeführt werden. Die Verwendung eines Verknüpfungshinweises wird mit einem impliziten Hinweis geliefert
FORCE ORDER
, der die Verknüpfungsreihenfolge an die Textform anpasst und viele Optimierungserkundungsregeln deaktiviert, die zu einer erneuten Schätzung der Kardinalität führen können.Dies entspricht dem Hinweis auf einen Join, schränkt jedoch die Auswahl des physischen Join-Operators nicht ein. Auch hier ist es sehr wahrscheinlich, dass Sie einen vernünftigen Plan erhalten, wenn Sie die Reihenfolge der Abfrageverknüpfungen logisch geschrieben haben. Natürlich lassen Sie auf diese Weise einen Großteil der Fähigkeiten des Optimierers aus, was in allgemeineren Situationen möglicherweise nicht zu optimalen Ergebnissen führt.
Sie werden es wahrscheinlich nicht
FORCE ORDER
sehr oft verwenden wollen, da es sich um einen äußerst mächtigen Hinweis (Direktive) handelt, der umfassendere Auswirkungen hat, als nur die Reihenfolge der Verknüpfungen zu erzwingen. Dies verhindert beispielsweise, dass das Optimierungsprogramm Aggregate verschiebt und Teilaggregationen einführt. Ich rate sehr davon ab, diesen Hinweis zu verwenden, außer in Ausnahmefällen und von wirklich erfahrenen Tunern.Eine detaillierte Analyse würde mehr Zeit als bisher erfordern und Zugriff auf eine reine Statistikkopie der Datenbank.
quelle
Das Wo negiert das Linke
Warum es dem Optimierer schwer machen?
Bei 3 oder mehr schließt sich der Optimierer Defensive gehen TEND und in Schleife schließt sich wie Speicher schützt
ein oder Zustand in der Verknüpfung wird es auch in einer Schleife gehen neigen kommen - muss ich harte Beweise haben es jedes Mal geschehen - nein - immer noch eine Realität
Mit mehreren verbindet Pull Bedingungen aus dem , wo in der Verbindung , wenn Sie können
Oder noch besser - ich wette, das wird deine Hinweise oder deine Kraft treffen oder übertreffen
Das Problem mit Hinweisen ist, dass sie sich auf Daten in einem bestimmten Zustand beziehen. Schreiben Sie eine saubere Abfrage und lassen Sie den Optimierer seine Arbeit erledigen. Manchmal braucht es einfach mehr Statistiken, um das Richtige zu tun, aber dann wird es sich festsetzen.
Warum unterschiedliche Schätzungen. Ein anderer Plan. Beginnen Sie mit Abfragen, die dem Optimierer eine Kampfchance geben.
quelle