Nasz projekt prowadzi bardzo dużą, bardzo skomplikowaną bazę danych. Około miesiąc temu zauważyliśmy, że przestrzeń wykorzystywana przez indeksowane kolumny zawierające wartości null robi się zbyt duża. W odpowiedzi napisałem jako skrypt, który dynamicznie przeszukiwałby wszystkie indeksy jednokolumnowe zawierające więcej niż 1% wartości pustych, a następnie upuszczał i odtwarzał te indeksy jako indeksy filtrowane pod warunkiem, że wartość NIE była NULL. Spowodowałoby to upuszczenie i odtworzenie setek indeksów w bazie danych i zwykle zwolniłoby prawie 15% miejsca używanego przez całą bazę danych.
Teraz mam dwa pytania na ten temat:
A) Jakie są wady korzystania z filtrowanych indeksów w ten sposób? Zakładam, że poprawiłoby to tylko wydajność, ale czy wiąże się to z jakimś ryzykiem?
B) Otrzymaliśmy błędy ( „nie można upuścić indeksu XYZ, ponieważ on nie istnieje lub nie masz uprawnień” ) podczas upuszczania i odtwarzania indeksów, nawet jeśli po sprawdzeniu wszystko poszło dokładnie tak, jak oczekiwano. Jak to się może stać?
Dzięki za wszelką pomoc!
Edycja: W odpowiedzi na @Thomas Kejser
Cześć i dzięki, ale okazuje się, że to była katastrofa. W tym czasie nie rozumieliśmy kilku rzeczy, takich jak:
- Podczas zapytania SQLOS tworzy plany indeksów przed ustaleniem, że nie może używać wartości NULL do łączenia kolumn tabeli. IE, naprawdę potrzebujesz filtru klauzuli WHERE dopasowującego indeks do każdego filtrowanego indeksu użytego w zapytaniu, w przeciwnym razie indeks nie będzie w ogóle używany.
- Upuszczanie i tworzenie indeksów oraz ponowne zbędne aktualizowanie ich statystyk może jeszcze nie wystarczyć do stworzenia zaktualizowanych planów, co zakładaliśmy, że tak. Wydaje się, że w niektórych przypadkach tylko wystarczająco duże obciążenie zmusi SQL Server do ponownej oceny planów.
- Istnieją pewne egzotyki dotyczące funkcjonalności narzędzia planowania wykonania, które są trudne do ustalenia wyłącznie na podstawie zdrowego rozsądku i logiki. Z tysiącami wygenerowanych przez kod odmian różnych zapytań, pozornie bezużyteczne indeksy mogą pomóc w niektórych statystykach i planach zapytań, które ostatecznie są wykorzystywane w zapytaniach krytycznych.
Ostatecznie zmiany te zostały cofnięte. Filtrowane indeksy są więc potężnym narzędziem, ale trzeba naprawdę dokładnie zrozumieć, jakie dane są pobierane z tych kolumn. Tam, gdzie normalne indeksy oprócz problemów z przestrzenią są raczej łatwe do zastosowania, indeksy filtrowane reprezentują rozwiązania bardzo dostosowane. Z pewnością nie zastępują one zwykłego indeksu, a raczej rozszerzenie go w tych szczególnych okolicznościach, które są wymagane.
Odpowiedzi:
Bardzo ciekawe podejście. Moje poparcie dla kreatywności.
Ponieważ odzyskałeś miejsce, zakładam, że oryginalne indeksy nie są już na miejscu? Wady filtrowanych indeksów to:
W praktyce oznacza to, że musisz być bardzo ostrożny z filtrowanymi indeksami, ponieważ często skutkują strasznymi planami zapytań. Nie posunąłbym się nawet do nazwania ich bezużytecznymi, ale widzę je jako dodatek do tradycyjnych indeksów, a nie jako zamiennik (jak próbujesz to zrobić).
źródło
Thomas Kejser odpowiada na ten temat znacznie powyżej.
Właśnie pomyślałem o dodaniu 2 centów.
Widziałem, że niektóre filtrowane indeksy są używane (pokazane w planie wykonania) tylko wtedy, gdy dokładnie pasujesz do klauzuli where w zapytaniu jako gdzie w filtrowanym indeksie.
próbowałeś użyć widoków indeksowanych ? rzadkie kolumny ?
Uważam, że o ile masz tylko połączenia wewnętrzne, możesz utworzyć widok indeksowany zawierający klauzulę where swoich odfiltrowanych indeksów, a następnie możesz użyć tego widoku.
Może być więcej niż jeden widok. Ale podobnie jak w przypadku indeksów nieklastrowanych, zbyt wiele spowalnia zapisywanie.
Z mojego doświadczenia wynika, że zyskasz na czytaniu, ale będziesz musiał monitorować zapisy (wstawki i aktualizacje), szczególnie jeśli tabele są zaangażowane w replikację.
Jednak, jak rozumiem, twoimi głównymi obawami są
the null values
dlatego sugeruję SPARSE kolumny w twoich indeksach .Rzadkie kolumny są szczególnie odpowiednie dla przefiltrowanych indeksów
Ponieważ reklamowałem rzadkie kolumny, nie czułbym się dobrze, gdybym nie powiedział wam również o jego ograniczeniach:
W wyniku tego
Rozważ przykład> tabeli, która ma 600 rzadkich kolumn typu bigint.
więcej szczegółów na temat powyższego linku, jednak wolę opublikować tutaj również to ostrzeżenie:
Aparat baz danych programu SQL Server stosuje następującą procedurę w celu wprowadzenia tej zmiany:
1 - Dodaje nową kolumnę do tabeli w nowym rozmiarze i formacie pamięci.
2 - Dla każdego wiersza w tabeli aktualizuje i kopiuje wartość zapisaną w starej kolumnie do nowej kolumny.
3 - Usuwa starą kolumnę ze schematu tabeli.
4 - Odbudowuje tabelę (jeśli nie ma indeksu klastrowanego) lub odbudowuje indeks klastrowany w celu odzyskania miejsca używanego przez starą kolumnę.
źródło