statystyki są aktualne, ale oszacowanie jest nieprawidłowe

12

Kiedy to zrobię dbcc show_statistics ('Reports_Documents', PK_Reports_Documents), otrzymuję następujący wynik dla raportu o numerze ID 18698:

wprowadź opis zdjęcia tutaj

Dla tego zapytania:

SELECT * 
FROM Reports_Documents 
WHERE ReportID = 18698 option (recompile)

Otrzymuję plan kwerendy, który sprawia, że ​​wyszukiwanie klastrowane indeksuje się PK_Reports_Documentszgodnie z oczekiwaniami.

Ale zaskakuje mnie niepoprawna wartość Szacowanej liczby rzędów:

wprowadź opis zdjęcia tutaj

Zgodnie z tym :

Gdy przykładowa wartość zapytania klauzula WHERE jest równa wartości histogramu RANGE_HI_KEY, SQL Server użyje kolumny EQ_ROWS na histogramie, aby określić liczbę wierszy równych

Tak też bym się spodziewał, jednak wydaje się, że tak nie jest w prawdziwym życiu. Próbowałem też innych RANGE_HI_KEYwartości, które były obecne w histogramie dostarczonym przez show_statisticsi doświadczyłem tego samego. Ten problem w moim przypadku powoduje, że niektóre zapytania wykorzystują bardzo nieoptymalne plany wykonania, co powoduje, że czas wykonania wynosi kilka minut, podczas gdy mogę uruchomić go w ciągu 1 sekundy z podpowiedź do zapytania.

Podsumowując: czy ktoś może mi wyjaśnić, dlaczego EQ_ROWSz histogramu nie stosuje się szacowanej liczby wierszy i skąd się bierze niepoprawne oszacowanie?

Trochę więcej (być może pomocnych) informacji:

  • Automatyczne tworzenie statystyk jest włączone, a wszystkie statystyki są aktualne.
  • Tabela, której dotyczy zapytanie, ma około 80 milionów wierszy.
  • PK_Reports_Documentsjest kombinacją PK składającą się z ReportID INTiDocumentID CHAR(8)

Zapytanie wydaje się ładować w sumie 5 różnych obiektów statystycznych, z których wszystkie zawierają ReportID+ inne kolumny z tabeli. Wszystkie zostały świeżo zaktualizowane. RANGE_HI_KEYw tabeli poniżej znajduje się najwyższa górna granica kolumny na histogramie.

+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
|                                  name                                   | stats_id | auto_created | user_created | Leading column Type | RANGE_HI_KEY | RANGE_ROWS | EQ_ROWS  | DISTINCT_RANGE_ROWS | AVG_RANGE_ROWS |
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
| PK_Reports_Documents                                                    |        1 |            0 |            0 | Stationary          |        18722 | 0          | 2228,526 |                   0 | 1              |
| _dta_index_Reports_Documents_42_1629248859__K1_K63_K14_K13_K22_K23_72_6 |       62 |            0 |            0 | Stationary          |        18698 | 0          | 2228,526 |                   0 | 1              |
| _dta_stat_1629248859_1_1_59                                             |       76 |            0 |            1 | Stationary          |        18686 | 50,56393   | 1        |                   0 | 13397,04       |
| _dta_stat_1629248859_1_22_14_18_12_6                                    |       95 |            0 |            1 | Stationary          |        18698 | 0          | 2228,526 |                   0 | 1              |
| _dta_stat_1629248859_1_7_14_4_23_62                                     |       96 |            0 |            1 | Stationary          |        18698 | 56,63327   | 21641,5  |                   0 | 14526,44       |
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+

sp_updatestats ma być uruchamiany co noc w celu aktualizacji statystyk.

użytkownik1151923
źródło

Odpowiedzi:

10

Jest na to proste rozwiązanie:

Porzuć wszystkie _dta_...statystyki i przestań ślepo stosować zalecenia DTA.

Więcej informacji

Szczególny problem polegał na tym, że dla danej kolumny istniało wiele zestawów statystyk. Dodatkowe dtastatystyki zostały utworzone przez próbkowanie danych (domyślne zachowanie dla statystyk niezwiązanych z indeksem).

Jak to często bywa w przypadku statystycznych próbek, uzyskane histogramy nie obejmowały pełnego zakresu niepowiązanych danych. W zapytaniu zdarzyło się wybrać wartość, która była poza histogramem, co skutkowało oszacowaniem 1-wierszowym.

Dokładne zachowanie optymalizatora zapytań, gdy istnieje wiele zestawów statystyk dla tej samej kolumny, nie jest w pełni udokumentowane. Zwykle preferuje statystyki „pełnego skanowania” niż próbkowane, ale preferuje także statystyki ostatnio aktualizowane niż starsze.

Aaron Bertrand
źródło
To rzeczywiście działa. Nie stworzyłem jednak _dta_statystyk, były tam od pierwszego spojrzenia na DB. Nie wiedziałem, że stosowanie zaleceń może mieć tak niekorzystne skutki ...
1151923