Woher weiß SQL Server, dass Prädikate korreliert sind?


15

Bei der Diagnose von SQL Server 2008 R2-Abfragen mit schlechter Kardinalitätsschätzung (trotz einfacher Indizierung, aktueller Statistiken usw.) und daher schlechten Abfrageplänen wurde ein möglicherweise verwandter KB-Artikel gefunden: UPDATE: Schlechte Leistung beim Ausführen einer Abfrage das korrelierte UND-Prädikate in SQL Server 2008 oder in SQL Server 2008 R2 oder in SQL Server 2012 enthält

Ich kann mir vorstellen, was der KB-Artikel unter "korreliert" versteht, z. B. zielen Prädikat 2 und Prädikat 1 weitgehend auf dieselben Zeilen ab.

Aber ich weiß nicht, wie SQL Server über diese Zusammenhänge Bescheid weiß. Benötigt eine Tabelle einen mehrspaltigen Index, der Spalten aus beiden Prädikaten enthält? Verwendet SQL Statistiken, um zu überprüfen, ob Werte aus einer Spalte mit einer anderen korrelieren? Oder wird eine andere Methode angewendet?

Ich frage dies aus zwei Gründen:

  1. um festzustellen, welche meiner Tabellen und Abfragen mit diesem Hotfix verbessert werden könnten
  2. um zu wissen, was ich bei der Indizierung, Statistik usw. tun soll, um # 1 zu beeinflussen

Antworten:


20

Betrachten Sie den unten gezeigten einfachen AdventureWorks- Abfrage- und Ausführungsplan. Die Abfrage enthält Prädikate, die mit verknüpft sind AND. Die Kardinalitätsschätzung des Optimierers beträgt 41.211 Zeilen:

-- Estimate 41,211 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

Standardausführungsplan

Standardstatistik verwenden

Bei nur einspaltigen Statistiken erstellt der Optimierer diese Schätzung, indem er die Kardinalität für jedes Prädikat separat schätzt und die resultierenden Selektivitäten miteinander multipliziert. Diese Heuristik geht davon aus, dass die Prädikate völlig unabhängig sind.

Durch die Aufteilung der Abfrage in zwei Teile wird die Berechnung übersichtlicher:

-- Estimate 68,336.4 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336;

Die Tabelle "Transaktionsverlauf" enthält insgesamt 113.443 Zeilen, sodass die Schätzung von 68.336,4 eine Selektivität von 68336,4 / 113443 = 0,60238533 für dieses Prädikat darstellt. Diese Schätzung wird anhand der Histogramminformationen für die TransactionIDSpalte und der in der Abfrage angegebenen Konstantenwerte ermittelt.

-- Estimate 68,413 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

Dieses Prädikat hat eine geschätzte Selektivität von 68413.0 / 113443 = 0.60306056 . Es wird wiederum aus den konstanten Werten des Prädikats und dem Histogramm des TransactionDateStatistikobjekts berechnet .

Unter der Annahme, dass die Prädikate vollständig unabhängig sind, können wir die Selektivität der beiden Prädikate zusammen schätzen, indem wir sie miteinander multiplizieren. Die endgültige Kardinalitätsschätzung wird erhalten, indem die resultierende Selektivität mit den 113.443 Zeilen in der Basistabelle multipliziert wird:

0,60238533 * 0,60306056 * 113443 = 41210,987

Nach dem Runden ist dies die Schätzung von 41.211, die in der ursprünglichen Abfrage angezeigt wird (der Optimierer verwendet auch intern Gleitkomma-Mathematik).

Keine gute Schätzung

Die Spalten TransactionIDund TransactionDatehaben eine enge Korrelation im AdventureWorks-Datensatz (wie dies bei monoton ansteigenden Schlüsseln und Datumsspalten häufig der Fall ist). Diese Korrelation bedeutet, dass die Unabhängigkeitsannahme verletzt wird. Infolgedessen enthält der Abfrageplan nach der Ausführung 68.095 Zeilen anstelle der geschätzten 41.211:

Plan nach der Ausführung

Ablaufverfolgungsflag 4137

Durch Aktivieren dieses Ablaufverfolgungsflags werden die Heuristiken geändert, die zum Kombinieren von Prädikaten verwendet werden. Anstatt völlige Unabhängigkeit anzunehmen, geht der Optimierer davon aus, dass die Selektivitäten der beiden Prädikate nahe genug beieinander liegen, sodass eine Korrelation wahrscheinlich ist:

-- Estimate 68,336.4
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13'
OPTION (QUERYTRACEON 4137);

Denken Sie daran, dass das TransactionIDPrädikat allein 68.336,4 Zeilen und das TransactionDatePrädikat allein 68.413 Zeilen geschätzt hat. Der Optimierer hat die niedrigere dieser beiden Schätzungen gewählt, anstatt die Selektivitäten zu multiplizieren.

Dies ist natürlich nur eine andere Heuristik, die jedoch dazu beitragen kann, die Schätzungen für Abfragen mit korrelierten ANDPrädikaten zu verbessern . Jedes Prädikat wird auf mögliche Korrelation geprüft, und es werden andere Anpassungen vorgenommen, wenn viele ANDKlauseln betroffen sind. Dieses Beispiel dient jedoch dazu, die Grundlagen zu veranschaulichen.

Mehrspaltige Statistiken

Diese können bei Abfragen mit Korrelationen hilfreich sein, aber die Histogramminformationen basieren immer noch ausschließlich auf der führenden Spalte der Statistik. Die folgenden mehrspaltigen Statistikkandidaten unterscheiden sich daher in einem wichtigen Punkt:

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionID TransactionDate]
ON Production.TransactionHistory
    (TransactionID, TransactionDate);

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionDate TransactionID]
ON Production.TransactionHistory
    (TransactionDate, TransactionID);

Wenn wir nur eine davon nehmen, können wir sehen, dass die einzige zusätzliche Information die zusätzlichen Ebenen der "All" -Dichte sind. Das Histogramm enthält nur noch detaillierte Informationen zur TransactionDateSpalte.

DBCC SHOW_STATISTICS
    (
        'Production.TransactionHistory', 
        'stats Production.TransactionHistory TransactionDate TransactionID'
    );

Mehrspaltenstatistik

Mit diesen mehrspaltigen Statistiken ...

SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

... der Ausführungsplan zeigt eine Schätzung, die genau der entspricht, als nur einspaltige Statistiken verfügbar waren:

Mehrspaltiger Statistikplan

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.