Mam zapytanie, które korzysta z funkcji w predykacie, mniej więcej tak:
commentType = 'EL'
AND commentDateTime >= DATEADD(month,datediff(month,0,getdate()) - 13,0)
Mam filtrowany indeks na commentType, który ma 40 tys. Wierszy, a kiedy uruchamiam zapytanie, szacunkowa liczba wierszy dla szukania indeksu jest bardzo dokładna (około 11 tys.), Ale w następnym kroku (operator sortowania) całkowicie ignoruje statystyki i po prostu szacuje całkowitą liczbę wierszy w przefiltrowanym indeksie.
Dlaczego to się dzieje? Znam podstawy dotyczące sargability i przetestowałem dla zachowania rozsądku, zastępując dateadd rzeczywistą datą (01.01.2014) i voila ... Sortowanie zaczęło poprawnie zgadywać liczbę wierszy ...
Dlaczego tak się dzieje i jak mogę to naprawić? Nie mogę podać ustalonej daty ...
sql-server
index
statistics
MrKudz
źródło
źródło
DATEADD(month,datediff(month,0,getdate()) - 13,0)
nie ma dla mnie sensu. Co próbujesz z tym zrobić? Czy można to poprawić / uprościć?DATEADD(month, -13, DATEADD(day, 1-DATEPART(day, SYSDATETIME()))
sprawdzić, czy jest jakaś różnica?(commentType, commentDate)
, czy działa tam lepiej? Po prostu filtrowane indeksy mogą czasem błędnie zgłaszać szacunki w różnych punktach planów. Oszacowanie wydaje się wyjściem, zgłaszając całkowitą liczbę w przefiltrowanym indeksie, ale tak naprawdę plan jest wyświetlany nieprawidłowo.Odpowiedzi:
Uważam, że twoje szacunki są błędne z powodu błędu estymatora, który zamienia dwa argumenty DATEDIFF. Mówię o tym tutaj:
Obejściem tego problemu jest obliczenie pierwszego dnia 13 miesięcy temu bez użycia DATEDIFF (2008+):
Nie jestem pozytywny , że zajmie się szacunek (nie testowałem z filtrowanych indeksów, a nie jestem pewien, co ten rodzaj jest rzeczywiście robi i dlaczego to ma inny szacunek bez planu i / lub w pozostałej części zapytania ).
Poprawka, którą Microsoft zaleca, to użycie TF 4199, ale nie jestem pewien, czy właśnie to musisz zrobić tutaj:
Inną opcją byłoby upewnienie się, że korzystasz z najnowszej wersji SP / CU dla dowolnej wersji SQL Server, której używasz, ponieważ twierdzą, że zostało to naprawione w następującym artykule KB (choć nadal będzie to wymagało użycia TF 4199 chyba że masz rok 2014 lub lepszy):
Poprawka może zostać uzyskana w następujących wersjach:
(Następnym razem podaj wyniki
SELECT @@VERSION
swojego pytania).Zwrócę uwagę, że artykuł z bazy wiedzy mówi, że DATEDIFF może nie doceniać liczby wierszy, co jest przeciwieństwem tego, co dzieje się w twoim scenariuszu. To nie znaczy, że poprawki cię nie dotyczą; Myślę, że sformułowanie artykułu z bazy wiedzy jest niedokładne, ponieważ szacunki mogą iść w obie strony w zależności od danych i zakresu, na który patrzysz.
Mój post na blogu powyżej potwierdził, że zamiana nie występuje już w 2014 roku i później. Dla bezpieczeństwa prawdopodobnie usunęłbym DATEDIFF z predykatu i użyłbym innej metody do obliczenia początku zakresu. Nie sugeruję przekroczenia 4199 lub używania dynamicznego SQL, aby zapobiec złej zamianie.
źródło