Wie schätzt der Optimierer von SQL Server die Anzahl der Zeilen in einer verknüpften Tabelle?

13

Ich führe diese Abfrage in der AdventureWorks2012- Datenbank aus:

SELECT 
    s.SalesOrderID,
    d.CarrierTrackingNumber,
    d.ProductID,
    d.OrderQty
FROM Sales.SalesOrderHeader s 
JOIN Sales.SalesOrderDetail d 
    ON s.SalesOrderID = d.SalesOrderID
WHERE s.CustomerID = 11077

Wenn ich mir den geschätzten Ausführungsplan ansehe, sehe ich Folgendes:

Bildbeschreibung hier eingeben

Die anfängliche Indexsuche (oben rechts) verwendet den Index IX_SalesOrderHeader_CustomerID und durchsucht das Literal 11077. Es hat eine Schätzung von 2.6192 Zeilen.

Bildbeschreibung hier eingeben

Wenn ich benutze DBCC SHOW_STATISTICS ('Sales.SalesOrderHeader', 'IX_SalesOrderHeader_CustomerID') WITH HISTOGRAM, zeigt dies, dass der Wert 11077 zwischen den beiden abgetasteten Schlüsseln 11019 und 11091 liegt.

Bildbeschreibung hier eingeben

Die durchschnittliche Anzahl unterschiedlicher Zeilen zwischen 11019 und 11091 beträgt 2,619718 oder ist auf 2,61972 gerundet. Dies ist der Wert der geschätzten Zeilen, die für die Indexsuche angezeigt werden.

Der Teil, den ich nicht verstehe, ist die geschätzte Anzahl der Zeilen für die Clustered-Index-Suche anhand der SalesOrderDetail-Tabelle.

Bildbeschreibung hier eingeben

Wenn ich renne DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail', 'PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID'):

Bildbeschreibung hier eingeben

Die Dichte der SalesOrderID (der ich beitrete) beträgt also 3.178134E-05. Dies bedeutet, dass 1 / 3.178134E-05 (31465) der Anzahl der eindeutigen SalesOrderID-Werte in der SalesOrderDetail-Tabelle entspricht.

Wenn im SalesOrderDetail 31465 eindeutige SalesOrderIDs enthalten sind, beträgt die durchschnittliche Anzahl der Zeilen pro SalesOrderID bei einer geraden Verteilung 121317 (Gesamtanzahl der Zeilen) geteilt durch 31465. Der Durchschnitt liegt bei 3,85561

Wenn also die geschätzte Anzahl der zu durchschleifenden Zeilen 2.61972 beträgt und der Durchschnitt in 3.85561 zurückgegeben werden soll, würde ich annehmen, dass die geschätzte Anzahl der Zeilen 2.61972 * 3.85561 = 10.10062 beträgt.

Die geschätzte Anzahl der Zeilen beträgt jedoch 11,4867.

Ich denke, mein Verständnis der zweiten Schätzung ist falsch und die unterschiedlichen Zahlen scheinen darauf hinzudeuten. Was vermisse ich?

8kb
quelle

Antworten:

20

Ich denke, mein Verständnis der zweiten Schätzung ist falsch und die unterschiedlichen Zahlen scheinen darauf hinzudeuten. Was vermisse ich?

Bei Verwendung des SQL Server 2012-Kardinalitätsschätzers bestimmt die Selektivität des Joins die geschätzte Anzahl der Zeilen auf der Innenseite des Joins mit verschachtelten Schleifen und nicht umgekehrt.

Die 11.4867-Zahl wird abgeleitet (zur Anzeige im Showplan), indem die berechnete geschätzte Kardinalität der Join-Ausgabe (30.0919) durch die Anzahl der Iterationen (2.61972) dividiert wird. Das Ergebnis unter Verwendung von Gleitkomma-Arithmetik mit einfacher Genauigkeit ist 11,4867 .

So einfach ist das wirklich. Beachten Sie, dass die (logische) Join-Selektivität unabhängig von der Auswahl des physischen Join-Operators ist. Es bleibt gleich, ob der Join letztendlich mit einem physischen Operator für verschachtelte Schleifen, Hash oder Zusammenführung ausgeführt wird.

In SQL Server 2012 und früheren Versionen wird die Join-Selektivität (als Ganzes) anhand der SalesOrderIDHistogramme aus jeder Tabelle geschätzt (berechnet für jeden Histogrammschritt nach der Ausrichtung der Schrittgrenzen mithilfe linearer Interpolation, falls erforderlich). Das SalesOrderIDmit der SalesOrderHeaderTabelle verknüpfte Histogramm wird auch für den Skalierungseffekt des unabhängigen CustomerIDFilters angepasst .

Das heißt nicht, dass an der in der Frage vorgeschlagenen alternativen Berechnung etwas grundsätzlich „falsch“ ist. Es werden einfach andere Annahmen getroffen. Es wird immer verschiedene Möglichkeiten geben, Schätzungen für eine bestimmte Folge von logischen Operationen zu berechnen oder zu kombinieren. Es gibt keine allgemeine Garantie dafür, dass unterschiedliche statistische Methoden, die auf dieselben Daten angewendet werden, dieselben Antworten liefern oder dass eine Methode immer der anderen überlegen ist. Inkonsistenzen, die sich aus der Anwendung verschiedener statistischer Methoden ergeben, können sogar innerhalb eines einzigen endgültigen Ausführungsplans auftreten, obwohl sie selten bemerkt werden.

Als Randnotiz verwendet der SQL Server 2014-Kardinalitätsschätzer einen anderen Ansatz zum Kombinieren der durch unabhängige Filter angepassten Histogramminformationen ( "Grobausrichtung" ), was zu einer anderen endgültigen Schätzung von 10.1006 Zeilen für diese Abfrage führt:

Plan for computation:

  CSelCalcExpressionComparedToExpression
  (QCOL: [s].SalesOrderID x_cmpEq QCOL: [d].SalesOrderID)

Loaded histogram for column QCOL: [s].SalesOrderID from stats with id 1
Loaded histogram for column QCOL: [d].SalesOrderID from stats with id 1

Stats collection generated: 

  CStCollJoin(ID=4, **CARD=10.1006** x_jtInner)
      CStCollFilter(ID=3, CARD=2.61972)
          CStCollBaseTable(ID=1, CARD=31465 TBL: Sales.SalesOrderHeader AS TBL: s)
      CStCollBaseTable(ID=2, CARD=121317 TBL: Sales.SalesOrderDetail AS TBL: d)

Dies ist zufällig das gleiche Ergebnis wie die Berechnung in der Frage, obwohl die detaillierte Begründung unterschiedlich ist (dh sie basiert nicht auf einer angenommenen Implementierung von verschachtelten Schleifen).

Paul White 9
quelle