Wie wird die Anzahl der Histogrammschritte in der Statistik festgelegt?

11

Wie wird die Anzahl der Histogrammschritte in Statistik in SQL Server festgelegt?

Warum ist es auf 200 Schritte beschränkt, obwohl meine Schlüsselspalte mehr als 200 verschiedene Werte hat? Gibt es einen entscheidenden Faktor?


Demo

Schemadefinition

CREATE TABLE histogram_step
  (
     id   INT IDENTITY(1, 1),
     name VARCHAR(50),
     CONSTRAINT pk_histogram_step PRIMARY KEY (id)
  )

Einfügen von 100 Datensätzen in meine Tabelle

INSERT INTO histogram_step
            (name)
SELECT TOP 100 name
FROM   sys.syscolumns

Aktualisieren und Überprüfen der Statistiken

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step)

Histogrammschritte:

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            1 |          0 |       1 |                   0 |              1 |
|            3 |          1 |       1 |                   1 |              1 |
|            5 |          1 |       1 |                   1 |              1 |
|            7 |          1 |       1 |                   1 |              1 |
|            9 |          1 |       1 |                   1 |              1 |
|           11 |          1 |       1 |                   1 |              1 |
|           13 |          1 |       1 |                   1 |              1 |
|           15 |          1 |       1 |                   1 |              1 |
|           17 |          1 |       1 |                   1 |              1 |
|           19 |          1 |       1 |                   1 |              1 |
|           21 |          1 |       1 |                   1 |              1 |
|           23 |          1 |       1 |                   1 |              1 |
|           25 |          1 |       1 |                   1 |              1 |
|           27 |          1 |       1 |                   1 |              1 |
|           29 |          1 |       1 |                   1 |              1 |
|           31 |          1 |       1 |                   1 |              1 |
|           33 |          1 |       1 |                   1 |              1 |
|           35 |          1 |       1 |                   1 |              1 |
|           37 |          1 |       1 |                   1 |              1 |
|           39 |          1 |       1 |                   1 |              1 |
|           41 |          1 |       1 |                   1 |              1 |
|           43 |          1 |       1 |                   1 |              1 |
|           45 |          1 |       1 |                   1 |              1 |
|           47 |          1 |       1 |                   1 |              1 |
|           49 |          1 |       1 |                   1 |              1 |
|           51 |          1 |       1 |                   1 |              1 |
|           53 |          1 |       1 |                   1 |              1 |
|           55 |          1 |       1 |                   1 |              1 |
|           57 |          1 |       1 |                   1 |              1 |
|           59 |          1 |       1 |                   1 |              1 |
|           61 |          1 |       1 |                   1 |              1 |
|           63 |          1 |       1 |                   1 |              1 |
|           65 |          1 |       1 |                   1 |              1 |
|           67 |          1 |       1 |                   1 |              1 |
|           69 |          1 |       1 |                   1 |              1 |
|           71 |          1 |       1 |                   1 |              1 |
|           73 |          1 |       1 |                   1 |              1 |
|           75 |          1 |       1 |                   1 |              1 |
|           77 |          1 |       1 |                   1 |              1 |
|           79 |          1 |       1 |                   1 |              1 |
|           81 |          1 |       1 |                   1 |              1 |
|           83 |          1 |       1 |                   1 |              1 |
|           85 |          1 |       1 |                   1 |              1 |
|           87 |          1 |       1 |                   1 |              1 |
|           89 |          1 |       1 |                   1 |              1 |
|           91 |          1 |       1 |                   1 |              1 |
|           93 |          1 |       1 |                   1 |              1 |
|           95 |          1 |       1 |                   1 |              1 |
|           97 |          1 |       1 |                   1 |              1 |
|           99 |          1 |       1 |                   1 |              1 |
|          100 |          0 |       1 |                   0 |              1 |
+--------------+------------+---------+---------------------+----------------+

Wie wir sehen können, enthält das Histogramm 53 Schritte.

Wieder ein paar tausend Datensätze einfügen

INSERT INTO histogram_step
            (name)
SELECT TOP 10000 b.name
FROM   sys.syscolumns a
       CROSS JOIN sys.syscolumns b

Aktualisieren und Überprüfen der Statistiken

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step)

Jetzt werden die Histogrammschritte auf 4 Schritte reduziert

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            1 |          0 |       1 |                   0 |              1 |
|        10088 |      10086 |       1 |               10086 |              1 |
|        10099 |         10 |       1 |                  10 |              1 |
|        10100 |          0 |       1 |                   0 |              1 |
+--------------+------------+---------+---------------------+----------------+

Wieder ein paar tausend Datensätze einfügen

INSERT INTO histogram_step
            (name)
SELECT TOP 100000 b.name
FROM   sys.syscolumns a
       CROSS JOIN sys.syscolumns b

Aktualisieren und Überprüfen der Statistiken

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step) 

Jetzt werden die Histogrammschritte auf 3 Schritte reduziert

+--------------+------------+---------+---------------------+----------------+
| RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+--------------+------------+---------+---------------------+----------------+
|            1 |          0 |       1 |                   0 |              1 |
|       110099 |     110097 |       1 |              110097 |              1 |
|       110100 |          0 |       1 |                   0 |              1 |
+--------------+------------+---------+---------------------+----------------+

Kann mir jemand sagen, wie diese Schritte entschieden werden?

P ரதீப்
quelle
3
200 war eine willkürliche Wahl. Es hat nichts damit zu tun, wie viele unterschiedliche Werte Sie in einer bestimmten Tabelle haben. Wenn Sie wissen möchten, warum 200 ausgewählt wurde, müssen Sie einen Ingenieur aus dem SQL Server-Team der 90er Jahre fragen, nicht Ihre Kollegen
Aaron Bertrand
1
@ AaronBertrand - Danke. Also, wie werden diese Schritte entschieden
P ரதீப்
1
Es gibt keine Entscheidung. Die Obergrenze beträgt 200. Punkt. Technisch gesehen ist es 201, aber das ist eine Geschichte für einen anderen Tag.
Aaron Bertrand
1
Ich habe eine ähnliche Frage zu Intrastep-Schätzungen gestellt, könnte hilfreich sein dba.stackexchange.com/questions/148523/…
jesijesi

Antworten:

13

Ich werde diesen Beitrag auf die Erörterung einspaltiger Statistiken beschränken, da er bereits ziemlich langwierig ist und Sie daran interessiert sind, wie SQL Server die Daten in Histogrammschritte unterteilt. Bei mehrspaltigen Statistiken wird das Histogramm nur in der führenden Spalte erstellt.

Wenn SQL Server feststellt, dass eine Statistikaktualisierung erforderlich ist, wird eine versteckte Abfrage gestartet, die entweder alle Daten einer Tabelle oder ein Beispiel der Daten der Tabelle liest. Sie können diese Abfragen mit erweiterten Ereignissen anzeigen. In StatManSQL Server wird eine Funktion aufgerufen , die an der Erstellung der Histogramme beteiligt ist. Für einfache Statistikobjekte gibt es mindestens zwei verschiedene Arten von StatManAbfragen (es gibt verschiedene Abfragen für schnelle Statistikaktualisierungen, und ich vermute, dass die Funktion für inkrementelle Statistiken in partitionierten Tabellen auch eine andere Abfrage verwendet).

Der erste erfasst einfach alle Daten aus der Tabelle ohne Filterung. Sie können dies sehen, wenn die Tabelle sehr klein ist oder Sie Statistiken mit der FULLSCANOption sammeln :

CREATE TABLE X_SHOW_ME_STATMAN (N INT);
CREATE STATISTICS X_STAT_X_SHOW_ME_STATMAN ON X_SHOW_ME_STATMAN (N);

-- after gathering stats with 1 row in table
SELECT StatMan([SC0]) FROM
(
    SELECT TOP 100 PERCENT [N] AS [SC0] 
    FROM [dbo].[X_SHOW_ME_STATMAN] WITH (READUNCOMMITTED)
    ORDER BY [SC0] 
) AS _MS_UPDSTATS_TBL 
OPTION (MAXDOP 16);

SQL Server wählt die automatische Stichprobengröße basierend auf der Größe der Tabelle aus (ich denke, dass dies sowohl die Anzahl der Zeilen als auch der Seiten in der Tabelle ist). Wenn eine Tabelle zu groß ist, fällt die automatische Stichprobengröße unter 100%. Folgendes habe ich für dieselbe Tabelle mit 1 Million Zeilen erhalten:

-- after gathering stats with 1 M rows in table
SELECT StatMan([SC0], [SB0000]) FROM 
(
    SELECT TOP 100 PERCENT [SC0], step_direction([SC0]) over (order by NULL) AS [SB0000] 
    FROM 
    (
        SELECT [N] AS [SC0] 
        FROM [dbo].[X_SHOW_ME_STATMAN] TABLESAMPLE SYSTEM (6.666667e+001 PERCENT) WITH (READUNCOMMITTED) 
    ) AS _MS_UPDSTATS_TBL_HELPER 
    ORDER BY [SC0], [SB0000] 
) AS _MS_UPDSTATS_TBL
OPTION (MAXDOP 1);

TABLESAMPLEist dokumentiert , StatMan und step_direction jedoch nicht. Hier tastet SQL Server etwa 66,6% der Daten aus der Tabelle ab, um das Histogramm zu erstellen. Dies bedeutet, dass Sie möglicherweise eine andere Anzahl von Histogrammschritten erhalten, wenn Sie Statistiken (ohne FULLSCAN) für dieselben Daten aktualisieren . Ich habe das in der Praxis nie beobachtet, aber ich verstehe nicht, warum es nicht möglich wäre.

Lassen Sie uns einige Tests mit einfachen Daten durchführen, um zu sehen, wie sich die Statistiken im Laufe der Zeit ändern. Im Folgenden finden Sie einen Testcode, den ich geschrieben habe, um sequentielle Ganzzahlen in eine Tabelle einzufügen, Statistiken nach jeder Einfügung zu sammeln und Informationen zu den Statistiken in einer Ergebnistabelle zu speichern. Beginnen wir mit dem Einfügen von jeweils 1 Zeile bis zu 10000. Prüfstand:

DECLARE
@stats_id INT,
@table_object_id INT,
@rows_per_loop INT = 1,
@num_of_loops INT = 10000,
@loop_num INT;

BEGIN
    SET NOCOUNT ON;

    TRUNCATE TABLE X_STATS_RESULTS;

    SET @table_object_id = OBJECT_ID ('X_SEQ_NUM');
    SELECT @stats_id = stats_id FROM sys.stats
    WHERE OBJECT_ID = @table_object_id
    AND name = 'X_STATS_SEQ_INT_FULL';

    SET @loop_num = 0;
    WHILE @loop_num < @num_of_loops
    BEGIN
        SET @loop_num = @loop_num + 1;

        INSERT INTO X_SEQ_NUM WITH (TABLOCK)
        SELECT @rows_per_loop * (@loop_num - 1) + N FROM dbo.GetNums(@rows_per_loop);

        UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN; -- can comment out FULLSCAN as needed

        INSERT INTO X_STATS_RESULTS WITH (TABLOCK)
        SELECT 'X_STATS_SEQ_INT_FULL', @rows_per_loop * @loop_num, rows_sampled, steps 
        FROM sys.dm_db_stats_properties(@table_object_id, @stats_id);
        END;
END;

Für diese Daten steigt die Anzahl der Histogrammschritte schnell auf 200 (zuerst wird die maximale Anzahl von Schritten mit 397 Zeilen erreicht), bleibt bei 199 oder 200, bis 1485 Zeilen in der Tabelle enthalten sind, und nimmt dann langsam ab, bis das Histogramm nur noch 3 oder 4 enthält Schritte. Hier ist eine Grafik aller Daten:

erste Grafik

So sieht das Histogramm für 10.000 Zeilen aus:

RANGE_HI_KEY    RANGE_ROWS  EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1               0           1       0                   1
9999            9997        1       9997                1
10000           0           1       0                   1

Ist es ein Problem, dass das Histogramm nur 3 Schritte hat? Es sieht so aus, als ob Informationen aus unserer Sicht erhalten bleiben. Da der Datentyp ein INTEGER ist, können wir herausfinden, wie viele Zeilen in der Tabelle für jede Ganzzahl von 1 bis 10000 enthalten sind. In der Regel kann SQL Server dies auch herausfinden, obwohl dies in einigen Fällen nicht ganz funktioniert . In diesem SE-Beitrag finden Sie ein Beispiel dafür.

Was wird Ihrer Meinung nach passieren, wenn wir eine einzelne Zeile aus der Tabelle löschen und die Statistiken aktualisieren? Idealerweise erhalten wir einen weiteren Histogrammschritt, um zu zeigen, dass die fehlende Ganzzahl nicht mehr in der Tabelle enthalten ist.

DELETE FROM X_SEQ_NUM
WHERE X_NUM  = 1000;

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- still 3 steps

DELETE FROM X_SEQ_NUM
WHERE X_NUM  IN (2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- still 3 steps

Das ist ein bisschen enttäuschend. Wenn wir ein Histogramm von Hand erstellen würden, würden wir für jeden fehlenden Wert einen Schritt hinzufügen. SQL Server verwendet einen Allzweckalgorithmus, sodass wir für einige Datensätze möglicherweise ein geeigneteres Histogramm als den von ihm verwendeten Code erstellen können. Natürlich ist der praktische Unterschied zwischen 0 oder 1 Zeile aus einer Tabelle sehr gering. Ich erhalte die gleichen Ergebnisse beim Testen mit 20000 Zeilen, wobei jede Ganzzahl 2 Zeilen in der Tabelle enthält. Das Histogramm erhält keine Schritte, wenn ich Daten lösche.

RANGE_HI_KEY    RANGE_ROWS  EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1               0           2       0                   1
9999            19994       2       9997                2
10000           0           2       0                   1

Wenn ich mit 1 Million Zeilen teste, wobei jede Ganzzahl 100 Zeilen in der Tabelle enthält, erhalte ich etwas bessere Ergebnisse, kann aber dennoch von Hand ein besseres Histogramm erstellen.

truncate table X_SEQ_NUM;

BEGIN TRANSACTION;
INSERT INTO X_SEQ_NUM WITH (TABLOCK)
SELECT N FROM dbo.GetNums(10000);
GO 100
COMMIT TRANSACTION;

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- 4 steps

DELETE FROM X_SEQ_NUM
WHERE X_NUM  = 1000;

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- now 5 steps with a RANGE_HI_KEY of 998 (?)

DELETE FROM X_SEQ_NUM
WHERE X_NUM  IN (2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000);

UPDATE STATISTICS X_SEQ_NUM X_STATS_SEQ_INT_FULL WITH FULLSCAN;

DBCC SHOW_STATISTICS ('X_SEQ_NUM', 'X_STATS_SEQ_INT_FULL'); -- still 5 steps

Endgültiges Histogramm:

RANGE_HI_KEY    RANGE_ROWS  EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1               0           100     0                   1
998             99600       100     996                 100
3983            298100      100     2981                100
9999            600900      100     6009                100
10000           0           100     0                   1

Lassen Sie uns weiter mit sequentiellen Ganzzahlen, aber mit mehr Zeilen in der Tabelle testen. Beachten Sie, dass die manuelle Angabe einer Stichprobengröße für zu kleine Tabellen keine Auswirkung hat. Daher füge ich jeder Einfügung 100 Zeilen hinzu und sammle jedes Mal Statistiken mit bis zu 1 Million Zeilen. Ich sehe ein ähnliches Muster wie zuvor, außer wenn ich 637300 Zeilen in der Tabelle erreicht habe, werden nicht mehr 100% der Zeilen in der Tabelle mit der Standardabtastrate abgetastet. Wenn ich Zeilen gewinne, nimmt die Anzahl der Histogrammschritte zu. Möglicherweise liegt dies daran, dass SQL Server mit zunehmender Anzahl nicht abgetasteter Zeilen in der Tabelle mehr Lücken in den Daten aufweist. Ich treffe selbst bei 1 M Reihen nicht 200 Schritte, aber wenn ich weiterhin Reihen hinzufüge, erwarte ich, dass ich dort ankomme und irgendwann wieder nach unten gehe.

Grafik 2

Die X-Achse ist die Anzahl der Zeilen in der Tabelle. Wenn die Anzahl der Zeilen zunimmt, variieren die abgetasteten Zeilen ein wenig und überschreiten nicht 650.000.

Lassen Sie uns nun einige einfache Tests mit VARCHAR-Daten durchführen.

CREATE TABLE X_SEQ_STR (X_STR VARCHAR(5));
CREATE STATISTICS X_SEQ_STR ON X_SEQ_STR(X_STR);

Hier füge ich 200 Zahlen (als Zeichenfolgen) zusammen mit NULL ein.

INSERT INTO X_SEQ_STR
SELECT N FROM dbo.GetNums(200)
UNION ALL
SELECT NULL;

UPDATE STATISTICS X_SEQ_STR X_SEQ_STR ;

DBCC SHOW_STATISTICS ('X_SEQ_STR', 'X_SEQ_STR'); -- 111 steps, RANGE_ROWS is 0 or 1 for all steps

Beachten Sie, dass NULL immer einen eigenen Histogrammschritt erhält, wenn er in der Tabelle gefunden wird. SQL Server hätte mir genau 201 Schritte geben können, um alle Informationen zu erhalten, aber das hat es nicht getan. Technisch gesehen gehen Informationen verloren, weil '1111' beispielsweise zwischen '1' und '2' sortiert.

Versuchen wir nun, verschiedene Zeichen anstelle von ganzen Zahlen einzufügen:

truncate table X_SEQ_STR;

INSERT INTO X_SEQ_STR
SELECT CHAR(10 + N) FROM dbo.GetNums(200)
UNION ALL
SELECT NULL;

UPDATE STATISTICS X_SEQ_STR X_SEQ_STR ;

DBCC SHOW_STATISTICS ('X_SEQ_STR', 'X_SEQ_STR'); -- 95 steps, RANGE_ROWS is 0 or 1 or 2

Kein wirklicher Unterschied zum letzten Test.

Versuchen wir nun, Zeichen einzufügen, aber unterschiedliche Nummern für jedes Zeichen in die Tabelle aufzunehmen. Hat zum Beispiel CHAR(11)1 Zeile, CHAR(12)hat 2 Zeilen usw.

truncate table X_SEQ_STR;

DECLARE
@loop_num INT;

BEGIN
    SET NOCOUNT ON;

    SET @loop_num = 0;
    WHILE @loop_num < 200
    BEGIN
        SET @loop_num = @loop_num + 1;

        INSERT INTO X_SEQ_STR WITH (TABLOCK)
        SELECT CHAR(10 + @loop_num) FROM dbo.GetNums(@loop_num);
    END;
END;

UPDATE STATISTICS X_SEQ_STR X_SEQ_STR ;

DBCC SHOW_STATISTICS ('X_SEQ_STR', 'X_SEQ_STR'); -- 148 steps, most with RANGE_ROWS of 0

Nach wie vor bekomme ich immer noch nicht genau 200 Histogrammschritte. Viele der Schritte haben jedoch RANGE_ROWS0.

Für den letzten Test werde ich eine zufällige Zeichenfolge mit 5 Zeichen in jede Schleife einfügen und jedes Mal Statistiken sammeln. Hier ist der Code der zufälligen Zeichenfolge:

char((rand()*25 + 65))+char((rand()*25 + 65))+char((rand()*25 + 65))+char((rand()*25 + 65))+char((rand()*25 + 65))

Hier ist das Diagramm der Zeilen in Tabellen- und Histogrammschritten: Grafik 3

Beachten Sie, dass die Anzahl der Schritte nicht unter 100 sinkt, sobald sie auf und ab gehen. Ich habe von irgendwoher gehört (kann es aber momentan nicht beziehen), dass der SQL Server-Algorithmus zum Erstellen von Histogrammen Histogrammschritte kombiniert, da kein Platz mehr für sie vorhanden ist. Sie können also drastische Änderungen in der Anzahl der Schritte vornehmen, indem Sie nur ein paar Daten hinzufügen. Hier ist ein Beispiel der Daten, die ich interessant fand:

ROWS_IN_TABLE   ROWS_SAMPLED    STEPS
36661           36661           133
36662           36662           143
36663           36663           143
36664           36664           141
36665           36665           138

Selbst beim Abtasten mit FULLSCANkann das Hinzufügen einer einzelnen Zeile die Anzahl der Schritte um 10 erhöhen, konstant halten, dann um 2 verringern und dann um 3 verringern.

Was können wir daraus zusammenfassen? Ich kann nichts davon beweisen, aber diese Beobachtungen scheinen zuzutreffen:

  • SQL Server verwendet einen allgemeinen Algorithmus zum Erstellen der Histogramme. Bei einigen Datenverteilungen kann es möglich sein, eine vollständigere Darstellung der Daten von Hand zu erstellen.
  • Wenn die Tabelle NULL-Daten enthält und die Statistikabfrage diese findet, erhalten diese NULL-Daten immer einen eigenen Histogrammschritt.
  • Der in der Tabelle gefundene Mindestwert erhält einen eigenen Histogrammschritt mit RANGE_ROWS= 0.
  • Der in der Tabelle gefundene Maximalwert ist der endgültige Wert RANGE_HI_KEYin der Tabelle.
  • Wenn SQL Server mehr Daten abtastet, müssen möglicherweise vorhandene Schritte kombiniert werden, um Platz für die neu gefundenen Daten zu schaffen. Wenn Sie sich genügend Histogramme ansehen, werden möglicherweise allgemeine Werte für DISTINCT_RANGE_ROWSoder wiederholt RANGE_ROWS. Zum Beispiel wird 255 einige Male für RANGE_ROWSund DISTINCT_RANGE_ROWSfür den endgültigen Testfall hier angezeigt.
  • Bei einfachen Datenverteilungen kombiniert SQL Server möglicherweise sequentielle Daten zu einem Histogrammschritt, der keinen Informationsverlust verursacht. Wenn Sie jedoch Lücken zu den Daten hinzufügen, wird das Histogramm möglicherweise nicht so angepasst, wie Sie es sich erhoffen.

Wann ist das alles ein Problem? Es ist ein Problem, wenn eine Abfrage aufgrund eines Histogramms, das die Datenverteilung nicht so darstellen kann, dass das Abfrageoptimierungsprogramm gute Entscheidungen treffen kann, eine schlechte Leistung erbringt. Ich denke, es besteht die Tendenz zu denken, dass es immer besser ist, mehr Histogrammschritte zu haben, und dass es Bestürzung gibt, wenn SQL Server ein Histogramm für Millionen von Zeilen oder mehr generiert, aber nicht genau 200 oder 201 Histogrammschritte verwendet. Ich habe jedoch viele Statistikprobleme gesehen, selbst wenn das Histogramm 200 oder 201 Schritte hat. Wir haben keine Kontrolle darüber, wie viele Histogrammschritte SQL Server für ein Statistikobjekt generiert, sodass ich mir darüber keine Sorgen machen würde. Es gibt jedoch einige Schritte, die Sie ausführen können, wenn Abfragen mit schlechter Leistung aufgrund von Statistikproblemen auftreten. Ich werde einen äußerst kurzen Überblick geben.

In einigen Fällen kann es hilfreich sein, Statistiken vollständig zu sammeln. Bei sehr großen Tabellen kann die automatische Stichprobengröße weniger als 1% der Zeilen in der Tabelle betragen. Abhängig von der Datenstörung in der Spalte kann dies manchmal zu schlechten Plänen führen. Die Dokumentation von Microsoft für CREATE STATISTICS und UPDATE STATISTICS lautet wie folgt:

SAMPLE ist nützlich für spezielle Fälle, in denen der Abfrageplan basierend auf der Standardstichprobe nicht optimal ist. In den meisten Situationen ist es nicht erforderlich, SAMPLE anzugeben, da das Abfrageoptimierungsprogramm bereits Stichproben verwendet und standardmäßig die statistisch signifikante Stichprobengröße ermittelt, die zum Erstellen hochwertiger Abfragepläne erforderlich ist.

Für die meisten Workloads ist kein vollständiger Scan erforderlich, und die Standardabtastung ist ausreichend. Bestimmte Workloads, die für stark unterschiedliche Datenverteilungen empfindlich sind, erfordern möglicherweise eine größere Stichprobengröße oder sogar einen vollständigen Scan.

In einigen Fällen kann das Erstellen gefilterter Statistiken hilfreich sein. Möglicherweise haben Sie eine Spalte mit verzerrten Daten und vielen verschiedenen unterschiedlichen Werten. Wenn die Daten bestimmte Werte enthalten, nach denen häufig gefiltert wird, können Sie ein Statistikhistogramm nur für diese allgemeinen Werte erstellen. Das Abfrageoptimierungsprogramm kann die für einen kleineren Datenbereich definierten Statistiken anstelle der für alle Spaltenwerte definierten Statistiken verwenden. Es ist immer noch nicht garantiert, dass Sie 200 Schritte im Histogramm erhalten. Wenn Sie jedoch die gefilterten Statistiken für nur einen Wert erstellen, wird ein Histogramm diesen Wert schrittweise ausführen.

Die Verwendung einer partitionierten Ansicht ist eine Möglichkeit, mehr als 200 Schritte für eine Tabelle effektiv abzurufen. Angenommen, Sie können einen großen Tisch problemlos in einen Tisch pro Jahr aufteilen. Sie erstellen eine UNION ALLAnsicht, in der alle Jahrestabellen zusammengefasst sind. Jede Tabelle hat ein eigenes Histogramm. Beachten Sie, dass die in SQL Server 2014 eingeführten neuen inkrementellen Statistiken nur eine effizientere Aktualisierung der Statistiken ermöglichen. Das Abfrageoptimierungsprogramm verwendet nicht die Statistiken, die pro Partition erstellt werden.

Es gibt noch viele weitere Tests, die hier durchgeführt werden könnten. Ich empfehle Ihnen daher, zu experimentieren. Ich habe diese Tests mit SQL Server 2014 Express durchgeführt, sodass Sie wirklich nichts mehr aufhält.

Joe Obbish
quelle
4
Siehe google.com/patents/US6714938
Paul White 9