Jak decyduje liczba kroków histogramu w statystykach

11

Jak decyduje liczba kroków histogramu w statystykach w SQL Server?

Dlaczego jest ograniczony do 200 kroków, mimo że moja kolumna klucza zawiera ponad 200 różnych wartości? Czy jest jakiś decydujący czynnik?


Próbny

Definicja schematu

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

Wstawiam 100 rekordów do mojego stołu

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

Aktualizacja i sprawdzanie statystyk

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step)

Kroki histogramu:

+--------------+------------+---------+---------------------+----------------+
| 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 |
+--------------+------------+---------+---------------------+----------------+

Jak widać, na histogramie znajduje się 53 kroki.

Ponownie wstawiam kilka tysięcy rekordów

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

Aktualizacja i sprawdzanie statystyk

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step)

Teraz kroki histogramu są zredukowane do 4 kroków

+--------------+------------+---------+---------------------+----------------+
| 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 |
+--------------+------------+---------+---------------------+----------------+

Ponownie wstawiam kilka tysięcy rekordów

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

Aktualizacja i sprawdzanie statystyk

UPDATE STATISTICS histogram_step WITH fullscan

DBCC show_statistics('histogram_step', pk_histogram_step) 

Teraz kroki histogramu są zredukowane do 3 kroków

+--------------+------------+---------+---------------------+----------------+
| 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 |
+--------------+------------+---------+---------------------+----------------+

Czy ktoś może mi powiedzieć, w jaki sposób podejmowane są te kroki?

P ரதீப்
źródło
3
200 było arbitralnym wyborem. Nie ma to nic wspólnego z liczbą różnych wartości w konkretnej tabeli. Jeśli chcesz wiedzieć, dlaczego wybrano 200, musisz zapytać inżyniera z zespołu SQL Server z lat 90., a nie rówieśników
Aaron Bertrand
1
@AaronBertrand - Dzięki .. Więc w jaki sposób zdecydowano o liczbie kroków
P ரதீப்
1
Nie ma decyzji. Górna granica wynosi 200. Okres. Technicznie jest to 201, ale to historia na kolejny dzień.
Aaron Bertrand
1
Zadałem podobne pytanie dotyczące szacunków intrastep
jesijesi

Odpowiedzi:

14

Ograniczę ten post do omawiania statystyk z jedną kolumną, ponieważ będzie on już dość długi, a ty jesteś zainteresowany tym, jak SQL Server grupuje dane w etapy histogramu. W przypadku statystyk wielokolumnowych histogram jest tworzony tylko w kolumnie wiodącej.

Gdy SQL Server stwierdzi, że potrzebna jest aktualizacja statystyk, uruchamia ukryte zapytanie, które odczytuje wszystkie dane tabeli lub próbkę danych tabeli. Możesz przeglądać te zapytania z rozszerzonymi zdarzeniami. Istnieje funkcja wywoływana StatManw SQL Server, która jest zaangażowana w tworzenie histogramów. W przypadku prostych obiektów statystycznych istnieją co najmniej dwa różne typy StatManzapytań (istnieją różne zapytania do szybkich aktualizacji statystyk i podejrzewam, że funkcja statystyki przyrostowej w tabelach partycjonowanych również używa innego zapytania).

Pierwszy pobiera wszystkie dane z tabeli bez filtrowania. Możesz to zobaczyć, gdy stół jest bardzo mały lub zbierasz statystyki z FULLSCANopcją:

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 wybiera automatyczny rozmiar próbki na podstawie wielkości tabeli (myślę, że jest to zarówno liczba wierszy, jak i stron w tabeli). Jeśli tabela jest zbyt duża, automatyczny rozmiar próbki spada poniżej 100%. Oto, co dostałem dla tej samej tabeli z 1 milionami wierszy:

-- 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);

TABLESAMPLEjest udokumentowany, ale StatMan i krok_kierunek nie są. tutaj SQL Server próbkuje około 66,6% danych z tabeli w celu utworzenia histogramu. Oznacza to, że podczas aktualizacji statystyk (bez FULLSCAN) dla tych samych danych można uzyskać inną liczbę kroków histogramu . Nigdy nie obserwowałem tego w praktyce, ale nie rozumiem, dlaczego nie byłoby to możliwe.

Przeprowadźmy kilka testów na prostych danych, aby zobaczyć, jak statystyki zmieniają się w czasie. Poniżej znajduje się kod testowy, który napisałem, aby wstawić sekwencyjne liczby całkowite do tabeli, zebrać statystyki po każdej wstawce i zapisać informacje o statystykach w tabeli wyników. Zacznijmy od wstawienia 1 rzędu na raz do 10000. Łóżko testowe:

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;

Dla tych danych liczba kroków histogramu szybko wzrasta do 200 (najpierw osiąga maksymalną liczbę kroków z 397 wierszami), pozostaje na poziomie 199 lub 200, aż 1485 wierszy znajdzie się w tabeli, a następnie powoli maleje, aż histogram ma tylko 3 lub 4 kroki. Oto wykres wszystkich danych:

pierwszy wykres

Oto histogram dla 10 000 wierszy:

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

Czy to problem, że histogram składa się tylko z 3 kroków? Wygląda na to, że informacje są przechowywane z naszego punktu widzenia. Zauważ, że ponieważ typem danych jest INTEGER, możemy dowiedzieć się, ile wierszy znajduje się w tabeli dla każdej liczby całkowitej od 1 - 10000. Zwykle SQL Server również może to rozgryźć, chociaż są przypadki, w których to się nie sprawdza . Zobacz ten post SE na przykład.

Jak myślisz, co się stanie, jeśli usuniemy pojedynczy wiersz z tabeli i zaktualizujemy statystyki? Idealnie byłoby uzyskać kolejny krok histogramu, aby pokazać, że brakująca liczba całkowita nie jest już w tabeli.

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

To trochę rozczarowuje. Gdybyśmy budowali histogram ręcznie, dodalibyśmy krok dla każdej brakującej wartości. SQL Server korzysta z algorytmu ogólnego przeznaczenia, więc w przypadku niektórych zestawów danych możemy opracować bardziej odpowiedni histogram niż używany przez niego kod. Oczywiście praktyczna różnica między uzyskaniem 0 lub 1 rzędu ze stołu jest bardzo mała. Otrzymuję te same wyniki podczas testowania z 20000 wierszami, przy czym każda liczba całkowita ma 2 wiersze w tabeli. Histogram nie zyskuje kroków, gdy usuwam dane.

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

Jeśli wykonam test z 1 milionem wierszy z każdą liczbą całkowitą mającą 100 wierszy w tabeli, otrzymam nieco lepsze wyniki, ale nadal mogę ręcznie stworzyć lepszy histogram.

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

Ostateczny histogram:

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

Przetestujmy dalej za pomocą liczb całkowitych sekwencyjnych, ale z większą liczbą wierszy w tabeli. Zauważ, że dla tabel, które są zbyt małe, ręczne określenie wielkości próbki nie przyniesie żadnego efektu, więc dodam 100 wierszy do każdej wstawki i zbieram statystyki za każdym razem do 1 miliona wierszy. Widzę podobny wzór jak poprzednio, tyle że po przejściu do 637300 wierszy w tabeli nie próbuję już 100% wierszy w tabeli z domyślną częstotliwością próbkowania. Gdy zdobywam wiersze, liczba kroków histogramu rośnie. Być może dzieje się tak, ponieważ w programie SQL Server pojawia się więcej luk w danych, gdy rośnie liczba niespróbkowanych wierszy w tabeli. Nie uderzam w 200 kroków nawet przy 1 M rzędach, ale jeśli nadal będę dodawał rzędy, spodziewam się, że tam dotrę i w końcu zacznę wracać.

wykres 2

Oś X to liczba wierszy w tabeli. W miarę wzrostu liczby wierszy próbkowane wiersze różnią się nieco i nie przekraczają 650 tys.

Teraz zróbmy kilka prostych testów z danymi VARCHAR.

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

Tutaj wstawiam 200 liczb (jako ciągów) wraz z NULL.

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

Zauważ, że NULL zawsze otrzymuje własny krok histogramu, gdy zostanie znaleziony w tabeli. SQL Server mógł dać mi dokładnie 201 kroków, aby zachować wszystkie informacje, ale tego nie zrobił. Informacje techniczne są tracone, ponieważ „1111” sortuje na przykład między „1” a „2”.

Teraz spróbujmy wstawić różne znaki zamiast tylko liczb całkowitych:

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

Brak rzeczywistej różnicy od ostatniego testu.

Teraz spróbujmy wstawiać znaki, ale umieszczać różne liczby każdego znaku w tabeli. Na przykład CHAR(11)ma 1 wiersz, CHAR(12)ma 2 rzędy itp.

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

Tak jak poprzednio nadal nie otrzymuję dokładnie 200 kroków histogramu. Jednak wiele kroków ma wartość RANGE_ROWS0.

W końcowym teście wstawię losowy ciąg 5 znaków w każdej pętli i za każdym razem zbieram statystyki. Oto kod losowego ciągu:

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

Oto wykres wierszy w tabeli względem kroków histogramu: wykres 3

Pamiętaj, że liczba kroków nie spada poniżej 100, gdy zacznie rosnąć i spadać. Słyszałem skądś (ale nie mogę go teraz zdobyć), że algorytm budowania histogramu SQL Server łączy kroki histogramu, gdy kończy się dla nich miejsce. Możesz więc skończyć z drastycznymi zmianami liczby kroków, dodając trochę danych. Oto jedna próbka danych, które uznałem za interesujące:

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

Nawet przy próbkowaniu z FULLSCANdodaniem pojedynczego wiersza można zwiększyć liczbę kroków o 10, utrzymywać go na stałym poziomie, następnie zmniejszyć o 2, a następnie zmniejszyć o 3.

Co możemy z tego podsumować? Nie mogę tego udowodnić, ale te obserwacje wydają się być prawdziwe:

  • SQL Server używa ogólnego algorytmu do tworzenia histogramów. W przypadku niektórych dystrybucji danych może być możliwe ręczne utworzenie pełniejszej reprezentacji danych.
  • Jeśli w tabeli znajdują się dane NULL, a zapytanie statyczne je znajdzie, to dane NULL zawsze otrzymują własny krok histogramu.
  • Minimalna wartość znaleziona w tabeli otrzymuje własny krok histogramu z RANGE_ROWS= 0.
  • Maksymalna wartość znaleziona w tabeli będzie ostateczną wartością RANGE_HI_KEYw tabeli.
  • Gdy SQL Server próbkuje więcej danych, może być konieczne połączenie istniejących kroków, aby zrobić miejsce dla nowych danych, które znajdzie. Jeśli spojrzysz na wystarczającą liczbę histogramów, możesz zobaczyć powtarzające się wspólne wartości dla DISTINCT_RANGE_ROWSlub RANGE_ROWS. Na przykład 255 pokazuje wiele razy dla RANGE_ROWSi DISTINCT_RANGE_ROWSdla ostatniego przypadku testowego tutaj.
  • W przypadku prostych dystrybucji danych SQL Server łączy sekwencyjne dane w jeden krok histogramu, który nie powoduje utraty informacji. Jednak podczas dodawania luk do danych histogram może nie dostosować się w sposób, jaki można by oczekiwać.

Kiedy to wszystko stanowi problem? Jest to problem, gdy zapytanie działa słabo z powodu histogramu, który nie jest w stanie reprezentować rozkładu danych w sposób, który może pomóc w podejmowaniu dobrych decyzji przez optymalizator zapytań. Myślę, że istnieje tendencja do myślenia, że ​​posiadanie większej liczby kroków histogramu jest zawsze lepsze i może istnieć konsternacja, gdy SQL Server generuje histogram na milionach wierszy lub więcej, ale nie używa dokładnie 200 lub 201 kroków histogramu. Jednak widziałem wiele problemów ze statystykami, nawet jeśli histogram ma 200 lub 201 kroków. Nie mamy żadnej kontroli nad tym, ile kroków histogramu generuje SQL Server dla obiektu statystyki, więc nie martwię się o to. Istnieją jednak pewne kroki, które można wykonać, gdy wystąpią zapytania o niskiej wydajności spowodowane problemami ze statystykami. Dam bardzo krótki przegląd.

W niektórych przypadkach pomocne może być pełne gromadzenie statystyk. W przypadku bardzo dużych tabel wielkość automatycznej próbki może być mniejsza niż 1% wierszy w tabeli. Czasami może to prowadzić do złych planów w zależności od zakłóceń danych w kolumnie. Dokumentacja Microsofts dla CREATE STATISTICS i UPDATE STATISTICS mówi tyle samo:

SAMPLE jest przydatny w szczególnych przypadkach, w których plan zapytań oparty na domyślnym próbkowaniu nie jest optymalny. W większości sytuacji nie jest konieczne określanie PRÓBKI, ponieważ optymalizator zapytań już używa próbkowania i domyślnie określa statystycznie znaczący rozmiar próbki, zgodnie z wymaganiami dotyczącymi tworzenia wysokiej jakości planów zapytań.

W przypadku większości obciążeń pełne skanowanie nie jest wymagane, a domyślne próbkowanie jest wystarczające. Jednak niektóre obciążenia wrażliwe na bardzo różne dystrybucje danych mogą wymagać zwiększenia wielkości próbki lub nawet pełnego skanowania.

W niektórych przypadkach pomocne może być tworzenie filtrowanych statystyk. Możesz mieć kolumnę z wypaczonymi danymi i wieloma różnymi odrębnymi wartościami. Jeśli w danych często filtrowane są określone wartości, można utworzyć histogram statystyczny tylko dla tych wspólnych wartości. Optymalizator zapytań może korzystać ze statystyk zdefiniowanych dla mniejszego zakresu danych zamiast statystyk zdefiniowanych dla wszystkich wartości kolumn. Nadal nie masz gwarancji, że uzyskasz 200 kroków na histogramie, ale jeśli utworzysz filtrowane statystyki tylko dla jednej wartości, histogram krok tej wartości.

Korzystanie z widoku podzielonego na partycje jest jednym ze sposobów skutecznego uzyskania ponad 200 kroków dla tabeli. Załóżmy, że możesz łatwo podzielić duży stół na jeden stół rocznie. Tworzysz UNION ALLwidok, który łączy wszystkie tabele roczne. Każda tabela będzie miała własny histogram. Należy pamiętać, że nowe statystyki przyrostowe wprowadzone w SQL Server 2014 pozwalają tylko na bardziej wydajne aktualizacje statystyk. Optymalizator zapytań nie będzie korzystał ze statystyk tworzonych dla poszczególnych partycji.

Istnieje wiele innych testów, które można uruchomić tutaj, więc zachęcam do eksperymentowania. Zrobiłem te testy na SQL Server 2014 express, więc naprawdę nic Cię nie powstrzymuje.

Joe Obbish
źródło
4
Zobacz google.com/patents/US6714938
Paul White 9