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?
sql-server
statistics
P ரதீப்
źródło
źródło
Odpowiedzi:
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
StatMan
w SQL Server, która jest zaangażowana w tworzenie histogramów. W przypadku prostych obiektów statystycznych istnieją co najmniej dwa różne typyStatMan
zapytań (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
FULLSCAN
opcją: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:
TABLESAMPLE
jest 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 (bezFULLSCAN
) 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:
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:
Oto histogram dla 10 000 wierszy:
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.
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.
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.
Ostateczny histogram:
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ć.
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.
Tutaj wstawiam 200 liczb (jako ciągów) wraz z NULL.
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:
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.Tak jak poprzednio nadal nie otrzymuję dokładnie 200 kroków histogramu. Jednak wiele kroków ma wartość
RANGE_ROWS
0.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:
Oto wykres wierszy w tabeli względem kroków histogramu:
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:
Nawet przy próbkowaniu z
FULLSCAN
dodaniem 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:
RANGE_ROWS
= 0.RANGE_HI_KEY
w tabeli.DISTINCT_RANGE_ROWS
lubRANGE_ROWS
. Na przykład 255 pokazuje wiele razy dlaRANGE_ROWS
iDISTINCT_RANGE_ROWS
dla ostatniego przypadku testowego tutaj.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:
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 ALL
widok, 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.
źródło