SQL Server 2014 COUNT (DISTINCT x) ignoruje wektor gęstości statystyki dla kolumny x

15

W przypadku pliku, COUNT(DISTINCT)który ma ~ 1 miliard różnych wartości, otrzymuję plan zapytań z agregatem skrótu, który ma tylko ~ 3 miliony wierszy.

Dlaczego to się dzieje? SQL Server 2012 daje dobre oszacowanie, więc czy jest to błąd w SQL Server 2014, który powinienem zgłosić w Connect?

Zapytanie i słaba ocena

-- Actual rows: 1,011,719,166
-- SQL 2012 estimated rows: 1,079,130,000 (106% of actual)
-- SQL 2014 estimated rows: 2,980,240 (0.29% of actual)
SELECT COUNT(DISTINCT factCol5)
FROM BigFactTable
OPTION (RECOMPILE, QUERYTRACEON 9481) -- Include this line to use SQL 2012 CE

-- Stats for the factCol5 column show that there are ~1 billion distinct values
-- This is a good estimate, and it appears to be what the SQL 2012 CE uses
DBCC SHOW_STATISTICS (BigFactTable, _WA_Sys_00000005_24927208)
--All density   Average Length  Columns
--9.266754E-10  8               factCol5
SELECT 1 / 9.266754E-10
-- 1079126520.46229

Plan zapytań

wprowadź opis zdjęcia tutaj

Pełny skrypt

Oto pełne zgłoszenie sytuacji przy użyciu bazy danych zawierającej tylko statystyki .

Co próbowałem do tej pory

Zagłębiłem się w statystyki dla odpowiedniej kolumny i stwierdziłem, że wektor gęstości pokazuje około 1,1 miliarda różnych wartości. SQL Server 2012 korzysta z tej prognozy i tworzy dobry plan. Zaskakująco wygląda na to, że SQL Server 2014 ignoruje bardzo dokładne oszacowania podane w statystykach, a zamiast tego używa znacznie niższych oszacowań. Powoduje to znacznie wolniejszy plan, który nie rezerwuje prawie wystarczającej ilości pamięci i rozlewa się do tempdb.

Próbowałem flagi śledzenia 4199, ale to nie naprawiło sytuacji. Na koniec próbowałem zagłębić się w informacje o optymalizatorze za pomocą kombinacji flag śledzenia (3604, 8606, 8607, 8608, 8612), jak pokazano w drugiej połowie tego artykułu . Jednak nie byłem w stanie zobaczyć żadnych informacji wyjaśniających złe oszacowanie, dopóki nie pojawiło się w końcowym drzewie wyników.

Problem z połączeniem

Na podstawie odpowiedzi na to pytanie zgłosiłem to również jako problem w Connect

Geoff Patterson
źródło

Odpowiedzi:

14

Sposób, w jaki szacowana jest liczność, z pewnością wydaje mi się sprzeczny z intuicją. Wyliczenie odrębnej liczby (widoczne z rozszerzonymi zdarzeniami lub flagami śledzenia 2363 i 3604) to:

Wyprowadzanie statystyk

Zwróć uwagę na czapkę. Ogólna logika tego wydaje się bardzo rozsądna (nie może być bardziej wyraźnych wartości), ale ograniczenie jest stosowane na podstawie próbkowanych statystyk wielokolumnowych:

DBCC SHOW_STATISTICS 
    (BigFactTable, [PK_BigFactTable])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

Statystyki PK

To pokazuje 2980,235 wierszy próbkowanych z 3439431721 z wektorem gęstości na poziomie Col5 3,35544E-07. Odwrotność tego daje szereg odrębnych wartości 2980,235 zaokrąglonych za pomocą prawdziwej matematyki do 2980,240.

Teraz pytanie, biorąc pod uwagę próbkowane statystyki, jakie założenia powinien przyjąć model odnośnie liczby różnych wartości. Spodziewałbym się ekstrapolacji, ale nie zostało to zrobione i być może celowo.

Bardziej intuicyjnie, spodziewałbym się, że zamiast używać statystyk wielokolumnowych, sprawdziłby gęstość na Col5 (ale tak nie jest):

DBCC SHOW_STATISTICS 
    (BigFactTable, [_WA_Sys_00000005_24927208])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

Statystyki Col5

Tutaj gęstość wynosi 9.266754E-10, a wzajemność wynosi 1 079 126 528 .

W międzyczasie jednym oczywistym obejściem jest aktualizacja statystyk wielokolumnowych pełnym skanem. Drugim jest użycie oryginalnego estymatora liczności.

Element Connect, który otworzyłeś, próbkowane statystyki wielokolumnowe SQL 2014 zastępują dokładniejsze statystyki jednokolumnowe dla kolumn nieprzednich , jest oznaczony jako stały dla SQL Server 2017.

Paul White 9
źródło