Kiedy to zrobię dbcc show_statistics ('Reports_Documents', PK_Reports_Documents)
, otrzymuję następujący wynik dla raportu o numerze ID 18698:
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_Documents
zgodnie z oczekiwaniami.
Ale zaskakuje mnie niepoprawna wartość Szacowanej liczby rzędów:
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_KEY
wartości, które były obecne w histogramie dostarczonym przez show_statistics
i 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_ROWS
z 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_Documents
jest kombinacją PK składającą się zReportID INT
iDocumentID 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_KEY
w 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.
_dta_
statystyk, były tam od pierwszego spojrzenia na DB. Nie wiedziałem, że stosowanie zaleceń może mieć tak niekorzystne skutki ...