Warum erstellt SQL Server keine Histogramme für zusammengesetzte Spaltenstatistiken?

10

SQL Server hat eine Sache namens "mehrspaltige Statistik", aber es ist nicht das, was man denkt, dass es bedeuten würde.

Schauen wir uns die folgende Beispieltabelle an:

CREATE TABLE BadStatistics 
(
    IsArchived BIT NOT NULL,
    Id INT NOT NULL IDENTITY PRIMARY KEY,
    Mystery VARCHAR(200) NOT NULL
);

CREATE NONCLUSTERED INDEX BadIndex 
    ON BadStatistics (IsArchived, Mystery);

Damit werden zwei Statistiken für die beiden Indizes erstellt, die wir haben:

Statistiken für BadIndex:

+--------------+----------------+-------------------------+
| All density  | Average Length | Columns                 |
+--------------+----------------+-------------------------+
| 0.5          | 1              | IsArchived              |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 37             | IsArchived, Mystery     |
+--------------+----------------+-------------------------+
| 4.149378E-06 | 41             | IsArchived, Mystery, Id |
+--------------+----------------+-------------------------+

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 0            | 0          | 24398   | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+
| 1            | 0          | 216602  | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+

Statistiken für den Clustered-Index:

+--------------+----------------+---------+
| All density  | Average Length | Columns |
+--------------+----------------+---------+
| 4.149378E-06 | 4              | Id      |
+--------------+----------------+---------+

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
| 1            | 0          | 1       | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+
| 240999       | 240997     | 1       | 240997              | 1              |
+--------------+------------+---------+---------------------+----------------+
| 241000       | 0          | 1       | 0                   | 1              |
+--------------+------------+---------+---------------------+----------------+

(Ich habe die Tabelle mit zufälligen Stichprobendaten gefüllt, in denen etwa ein Zehntel der Zeilen nicht archiviert ist. Anschließend habe ich eine vollständige Aktualisierung der Scan-Statistiken durchgeführt.)

Warum verwendet das Histogramm der zweispaltigen Statistiken nur eine Spalte? Ich weiß , dass viele Menschen darüber geschrieben haben , dass es tut , aber was ist der Grund? In diesem Fall ist das gesamte Histogramm weniger nützlich, da die erste Spalte immer nur zwei Werte enthält. Warum sollten Statistiken so willkürlich eingeschränkt werden?

Bitte beachten Sie, dass sich diese Frage nicht auf mehrdimensionale Histogramme bezieht, die ein völlig anderes Tier sind. Es geht um eindimensionale Histogramme, wobei die einzelne Dimension die Tupel sind, die die jeweiligen, mehreren Spalten enthalten.

John
quelle

Antworten:

8

Hintergrund

Das aktuelle SQL Server-Modell verwendet nur einspaltige Histogramme und mehrspaltige Dichteinformationen. Einspaltige Histogramme werden verwendet, um die Selektivität für geeignete Prädikate, z . B. a = 1oder , abzuschätzen b > 50. Eine Abfrage mit mehreren Prädikaten kombiniert einfach die einzelnen Selektivitäten (mit Annahmen), um eine geschätzte Gesamtselektivität zu erzeugen.

Ein Beispiel finden Sie in meinem Artikel Kardinalitätsschätzung: Kombinieren der Dichtestatistik

Die Mehrspaltendichte informiert das Modell weiter, indem sie schwache Korrelationsinformationen für Prädikate mit mehreren Gleichheiten bereitstellt und Kardinalitäten für Aggregationen gruppiert.

Mit Indizes verknüpfte Statistiken sind ein opportunistisches Add-On zu diesem Modell: Die Engine kann genauso gut (normalerweise vollständige Scan-) Statistiken erfassen, während sie einen Index erstellt. SQL Server erstellt automatisch ein Histogramm mit führenden Spalten und Dichteinformationen für die anderen Schlüssel.

Histogramme für nicht führende Spalten in einem Index können bei Bedarf automatisch vom Abfrageprozessor oder im Voraus sp_createstatsmit der @indexonlyOption (unter anderem) erstellt werden.

Mehrspaltige Histogramme

Die Annahmen, die beim Kombinieren von einspaltigen Statistiken (wie oben) getroffen wurden, können die Realität der Daten gut genug modellieren oder nicht. In vielen Fällen führen die verfügbaren Optionen (exponentielles Backoff, Unabhängigkeit, minimale Selektivität) zu einer ausreichend guten Schätzung.

Wir haben auch Statistiken (und Indizes) als natürliche Lösung für führende Spaltenindizes mit niedriger Kardinalität gefiltert, wie im Fragenbeispiel. Wenn wir diese auf das logische Extrem bringen, kommen wir der mehrdimensionalen Statistik näher, um die es bei der Frage nicht geht.

Wenn die verfügbaren Modellierungsoptionen keine geeignete Schätzung liefern können, könnte ein mehrspaltiges statistisches Histogramm in einigen Fällen tatsächlich eine bessere Selektivitätsschätzung für geeignete Indexprädikate liefern. Es gibt einige Schwierigkeiten beim Kombinieren verschiedener Datentypen in verschiedenen Spalten, aber nichts Unüberwindbares.

Wir würden auch ein Histogramm für jede Ebene der Indexschlüssel benötigen (für beste Ergebnisse); Für einen Index (a, b, c)bedeutet dies also Histogramme (a, b)und (a, b, c)zusätzlich zum aktuellen einspaltigen Histogramm (a).

Der Mechanismus zur Erkennung veralteter Statistiken müsste ebenfalls geändert werden, um betroffene mehrspaltige Histogramme beizubehalten. Diese Histogramme werden wahrscheinlich häufiger neu erstellt als einspaltige Statistiken, einfach weil Änderungen an mehr Spalten sie betreffen.

All dies erhöht die Größe, Komplexität und den Wartungsaufwand.

Mehrspaltige Statistiken können (in begrenztem Umfang) mithilfe einer Statistik simuliert werden, die auf einer sorgfältig erstellten berechneten Spalte erstellt wurde, die auf mehrere Spalten verweist. Die Abfrage müsste ein Prädikat in der berechneten Spalte enthalten (oder eine genaue Textübereinstimmung für die zugrunde liegende Formel), um diese Statistik nutzen zu können. Es gibt wahrscheinlich nur sehr begrenzte Situationen, in denen dieser Ansatz praktisch ist. Trotzdem gibt es einige der gleichen Implementierungsprobleme wie bei automatischen mehrspaltigen Histogrammen.

Letztendlich wären die Designer selbst die einzigen, die mit Sicherheit sagen könnten, warum SQL Server keine mehrspaltigen Statistiken unterstützt. Wenn Sie der Meinung sind, dass Sie eine Produktverbesserung in diesem Bereich mit breiter Anwendbarkeit stark vertreten können, können Sie dies auf Connect oder über Ihren normalen Supportkanal vorschlagen .

Fußnote

In diesem Fall ist das gesamte Histogramm weniger nützlich, da die erste Spalte immer nur zwei Werte enthält

Das Histogramm liefert immer noch nützliche Informationen über die Verteilung der Werte in der führenden Spalte: Wenn die Statistiken gebaut wurden, gab es 24.398 Zeilen , in denen IsArchivedwaren falsch , und 216.602 Zeilen wo ist war wahr .

Darüber hinaus gibt das Statistikobjekt an, dass es (1 / 0,5) = 2 unterschiedliche Werte für IsArchived, (1 / 4,149378E-06) ~ = 241000 unterschiedliche Werte für (IsArchived, Mystery)mit einer durchschnittlichen Zeilengröße von 37 Bytes und dieselbe Häufigkeit für (IsArchived, Mystery, Id)mit gibt 4 zusätzliche Bytes pro Zeile.

Das sind alles gute Allzweckinformationen, die mit statistischen Informationen über andere Spalten kombiniert werden können, um eine Selektivitätsschätzung in Abfragen mit mehreren Prädikaten (wie erwähnt) zu erstellen.

Paul White 9
quelle