Statistiken. Sind mehrspaltige Histogramme möglich?

12

Ich denke an eine Situation, in der ich zwei Spalten mit hoher Dichte habe, aber diese Spalten nicht unabhängig sind.

Definition

Hier ist die Definition der Tabelle, die ich zu Testzwecken erstellt habe.

CREATE TABLE [dbo].[StatsTest](
    [col1] [int] NOT NULL,  --can take values 1 and 2 only
    [col2] [int] NOT NULL,  --can take integer values from 1 to 4 only
    [col3] [int] NOT NULL,  --integer. it has not relevance just to ensure that each row is different
    [col4]  AS ((10)*[col1]+[col2])  --a computed column ensuring that if two rows have different values in col1 or col2 have different values in col4 
) ON [PRIMARY]

Daten

Die Daten für das Experiment sind die folgenden

col1    col2    col3    col4
1       1       1       11
1       2       2       12
1       2       3       12
1       3       4       13
1       3       5       13
1       3       6       13
1       4       7       14
1       4       8       14
1       4       9       14
1       4       10      14
2       1       11      21
2       1       12      21
2       1       13      21
2       1       14      21
2       2       15      22
2       2       16      22
2       2       17      22
2       3       18      23
2       3       19      23
2       4       20      24

Schritt 1: Filtern nach col1

SELECT * FROM StatsTest WHERE col1=1

Wie erwartet schätzt das Abfrageoptimierungsprogramm die genaue Anzahl der Zeilen. Tatsächliche Anzahl der Zeilen = 10 und geschätzte Anzahl der Zeilen = 10

Schritt 2: Filtern nach col2

SELECT * FROM StatsTest WHERE col2=1

Wieder haben wir eine perfekte Schätzung.

Tatsächliche Anzahl der Zeilen = 5 und geschätzte Anzahl der Zeilen = 5

Schritt 3: Filtern nach col1 und col2

SELECT * FROM StatsTest WHERE col1=1 AND col2=1

Hier ist die Schätzung weit davon entfernt, der tatsächlichen Anzahl von Zeilen nahe zu kommen. Tatsächliche Anzahl der Zeilen = 1 und geschätzte Anzahl der Zeilen = 3.53553

Das Problem besteht darin, dass die implizite Annahme des Abfrageanalysators lautet, dass col1 und col2 unabhängig sind, dies jedoch nicht.

Schritt 4: Filtern nach col4

SELECT * FROM StatsTest WHERE col4 = 11

I kann durch col4 Filter = 11 die gleichen Ergebnisse wie die Abfrage in Schritt 3 zu bekommen, weil col4 eine berechnete Spalte ist und entsprechend die Art und Weise definiert worden spalte1 = 1 und Col2 = 1 entsprechen col4 = 11 hier jedoch Wie erwartet ist die Schätzung perfekt.

Tatsächliche Anzahl der Zeilen = 1 und geschätzte Anzahl der Zeilen = 1

Fazit / Frage

¿Ist diese künstliche und unelegante Lösung die einzige verfügbare Option, um beim Filtern nach zwei oder mehr nicht unabhängigen Spalten genaue Schätzungen zu erzielen? ¿Sind die berechnete Spalte und der Filter für die berechnete Spalte unbedingt erforderlich, um die tatsächliche Genauigkeit zu erzielen?

Beispiel in sqlfiddle

JGA
quelle
Warum nicht ein paar Indizes für col1 / 2 erstellen?
LowlyDBA
In der Tat habe ich, aber ich habe hier nicht aufgenommen, weil es nicht funktioniert hat. Für das Histogramm wird nur die erste Spalte berücksichtigt und die Dichte berücksichtigt nur die unterschiedliche Anzahl von Werten und nicht deren Verteilung
JGA

Antworten:

15

Sind mehrspaltige Histogramme möglich?

Keine echten mehrdimensionalen Histogramme, nein.

Ist diese künstliche und unelegante Lösung die einzige verfügbare Option, um beim Filtern nach zwei oder mehr nicht unabhängigen Spalten genaue Schätzungen zu erzielen?

SQL Server unterstützt zwar mehrspaltige Statistiken , erfasst jedoch nur Informationen zur durchschnittlichen Dichte (Korrelation) sowie ein Histogramm für die zuerst genannte Spalte. Sie sind nur für Gleichstellungsvergleiche nützlich.

Die Informationen zur durchschnittlichen Dichte erfassen keine Details, sodass Sie für jedes Wertepaar in einem zweispaltigen Statistikobjekt dieselbe Selektivität erhalten . In einigen Fällen können mehrspaltige Statistiken gut genug und besser als nichts sein. Mehrspaltige Statistiken werden automatisch auf mehrspaltigen Indizes erstellt.

Abhängig von der SQL Server-Version können Sie möglicherweise auch gefilterte Indizes und gefilterte Statistiken verwenden :

-- Filtered statistics example
CREATE STATISTICS stats_StatsTest_col2_col1_eq_1
ON dbo.StatsTest (col2)
WHERE col1 = 1;

CREATE STATISTICS stats_StatsTest_col2_col1_eq_2
ON dbo.StatsTest (col2)
WHERE col1 = 2;

Sie können auch eine indizierte Ansicht erstellen (die eigene Indizes und Statistiken unterstützt). Indizierte Sichten sind der Mechanismus hinter der DATE_CORRELATION_OPTIMIZATIONDatenbankeinstellung , eine wenig genutzte Funktion für tabellenübergreifende Korrelationen, die jedoch für den Grundgedanken der Frage gilt.

Ist die berechnete Spalte und der Filter nach der berechneten Spalte unbedingt erforderlich, um die tatsächliche Genauigkeit zu erhalten?

Es ist nicht die einzige Methode. Zusätzlich zu den bereits erwähnten Dingen können Sie auch die genaue Textdefinition der berechneten Spalte angeben, und das Optimierungsprogramm passt diese im Allgemeinen an Statistiken der berechneten Spalte an.

Es gibt auch Ablaufverfolgungsflags, die die Annahmen über mehrspaltige Korrelationen ändern. Außerdem wurde die Standardkorrelationsannahme in SQL Server 2014 (mit aktiviertem neuen Kardinalitätsschätzer) von "Unabhängigkeit" in "Exponentielles Backoff" geändert (weitere Details hier und hier ). Letztendlich ist dies jedoch nur eine andere Annahme. Es wird in vielen Fällen besser und in anderen schlechter sein.

Eine genaue Schätzung der Kardinalität ist nicht immer erforderlich, um einen guten Ausführungsplan zu erhalten. Es gibt immer einen Kompromiss zwischen der Generierung eines Plans, der für verschiedene Parameterwerte wiederverwendet werden kann, und einem Plan, der für eine bestimmte Ausführung optimal ist, aber nicht wiederverwendet wird.

Paul White 9
quelle