W poprzednim moim pytaniu, czy dobrym pomysłem jest wyłączenie eskalacji blokady podczas dodawania nowych kolumn obliczeniowych do tabeli? , Tworzę kolumnę obliczeniową:
ALTER TABLE dbo.tblBGiftVoucherItem
ADD isUsGift AS CAST
(
ISNULL(
CASE WHEN sintMarketID = 2
AND strType = 'CARD'
AND strTier1 LIKE 'GG%'
THEN 1
ELSE 0
END
, 0)
AS BIT
) PERSISTED;
Kolumna obliczana jest PERSISTED
i zgodnie z definicją obliczonej_kolumny (Transact-SQL) :
TRWAŁA
Określa, że aparat bazy danych fizycznie zapisze obliczone wartości w tabeli i zaktualizuje wartości, gdy zostaną zaktualizowane inne kolumny, od których zależy obliczona kolumna. Oznaczenie kolumny obliczanej jako PERSISTED pozwala na utworzenie indeksu na kolumnie obliczeniowej, która jest deterministyczna, ale nieprecyzyjna. Aby uzyskać więcej informacji, zobacz Indeksy dotyczące kolumn obliczanych. Wszelkie kolumny obliczane używane jako partycjonowane kolumny tabeli podzielonej na partycje muszą być wyraźnie oznaczone jako PERSISTED. wyrażenie wyliczone_kolumna musi być deterministyczne, gdy określono PERSISTED.
Ale kiedy próbuję utworzyć indeks w mojej kolumnie, pojawia się następujący błąd:
CREATE INDEX FIX_tblBGiftVoucherItem_incl
ON dbo.tblBGiftVoucherItem (strItemNo)
INCLUDE (strTier3)
WHERE isUsGift = 1;
Filtrowanego indeksu „FIX_tblBGiftVoucherItem_incl” nie można utworzyć w tabeli „dbo.tblBGiftVoucherItem”, ponieważ kolumna „isUsGift” w wyrażeniu filtru jest kolumną obliczoną. Przepisz wyrażenie filtru, aby nie zawierało tej kolumny.
Jak mogę utworzyć filtrowany indeks w kolumnie obliczanej?
lub
Czy istnieje alternatywne rozwiązanie?
źródło
WHERE (sintMarketID = 2 AND strType = 'CARD' AND strTier1 LIKE 'GG%')
.Odpowiedzi:
Niestety od SQL Server 2014 nie ma możliwości utworzenia miejsca, w
Filtered Index
którym filtr znajduje się w kolumnie obliczeniowej (niezależnie od tego, czy jest on utrwalony).Nastąpił Przedmiot Połącz otwarty od 2009 roku, więc proszę iść do przodu i zagłosuj na niego. Może Microsoft naprawi to pewnego dnia.
Aaron Bertrand ma artykuł, który omawia wiele innych problemów z indeksami filtrowanymi .
źródło
Chociaż nie można utworzyć filtrowanego indeksu na utrwalonej kolumnie, istnieje dość proste obejście, którego można użyć.
Jako test stworzyłem prostą tabelę z
IDENTITY
kolumną i utrwaloną kolumną obliczeniową na podstawie kolumny tożsamości:Następnie utworzyłem widok związany ze schematem na podstawie tabeli z filtrem w kolumnie obliczanej:
Następnie utworzyłem indeks klastrowy w widoku związanym ze schematem, który powoduje utrwalenie wartości przechowywanych w widoku, w tym wartości kolumny obliczanej:
Wstaw niektóre dane testowe do tabeli:
Utwórz element statystyk i indeks w widoku:
Wykonywanie
SELECT
instrukcji dla tabeli z utrwaloną kolumną może teraz automatycznie korzystać z utrwalonego widoku, jeśli optymalizator zapytań stwierdzi, że warto to zrobić:Rzeczywisty plan wykonania dla powyższego zapytania pokazuje, że optymalizator zapytań wybrał użycie utrwalonego widoku do zwrócenia wyników:
Być może zauważyłeś wyraźną konwersję w
WHERE
powyższym punkcie. Wyraźnie toCONVERT(INT, 26)
pozwala optymalizatorowi kwerendy poprawnie używać obiektu statystyki do oszacowania liczby wierszy, które zostaną zwrócone przez kwerendę. Jeśli napiszemy zapytanieWHERE pv.TestComputedColumn = 26
, optymalizator zapytań może nie oszacować poprawnie liczby wierszy, ponieważ 26 uważa się za aTINY INT
; może to spowodować, że SQL Server nie użyje utrwalonego widoku. Niejawne konwersje mogą być bardzo bolesne i opłaca się konsekwentnie używać odpowiednich typów danych do porównań i połączeń.Oczywiście wszystkie standardowe „gotchas” wynikające z używania wiązania schematu dotyczą powyższego scenariusza; może to uniemożliwić korzystanie z tego obejścia we wszystkich scenariuszach. Na przykład modyfikowanie tabeli podstawowej nie będzie już możliwe bez uprzedniego usunięcia powiązania schematu z widoku. Aby to zrobić, musisz usunąć indeks klastrowany z widoku.
Jeśli nie masz programu SQL Server Enterprise Edition, optymalizator zapytań nie będzie automatycznie używał utrwalonego widoku dla zapytań, które nie odwołują się bezpośrednio do widoku przy użyciu
WITH (NOEXPAND)
podpowiedzi. Aby wykorzystać zalety korzystania z utrwalonego widoku w wersjach innych niż Enterprise Edition, musisz ponownie napisać powyższe zapytanie w coś takiego:Dzięki Ian Ringrose za wskazanie powyższego ograniczenia Enterprise Edition oraz Paulowi Whiteowi za
(NOEXPAND)
podpowiedź.Ta odpowiedź Paula zawiera kilka interesujących szczegółów na temat optymalizatora zapytań w odniesieniu do utrwalonych widoków.
źródło
TestComputedColumn
zamiast. Ponieważ jednak indeks klastrowany zawiera wszystkie dane dla tabeli / widoku, zdecydowałem, że lepiej będzie użyć monotonicznie rosnącej liczby jako klucza klastrowania. Zauważ, że tak naprawdę nie testowałem tego przypuszczenia i może ono być w rzeczywistości niepoprawne dla niektórych wariantów repro.Od
Create Index
i jegowhere
klauzula nie jest to możliwe:Źródło: MSDN
źródło
Zanim obliczyliśmy kolumny, użyliśmy wyzwalaczy do obliczania wartości kolumn za każdym razem, gdy wiersz był zmieniany lub wstawiany.
(Można także użyć wyzwalacza do wstawienia / usunięcia PK elementu z 2. tabeli, która została następnie użyta w zapytaniach.)
źródło
Jest to próba usprawnienia pracy Maxa Vernona . W swoim rozwiązaniu sugeruje użycie 2 indeksów w widoku i obiektu statystycznego.
Pierwszy indeks jest klastrowany, co jest faktycznie wymagane, ponieważ w przeciwieństwie do indeksu nieklastrowanego w tabeli, błąd zostanie wygenerowany, jeśli spróbuje się utworzyć indeks nieklastrowany w widoku bez uprzedniego posiadania indeksu klastrowanego.
Drugi indeks jest indeksem nieklastrowanym, który jest używany jako indeks kwerendy. W sekcji komentarzy jego odpowiedzi zapytałem, co by się stało, gdyby zamiast indeksu nieklastrowanego użyto indeksu klastrowego.
Poniższa analiza próbuje odpowiedzieć na to pytanie.
Używam jego dokładnie tego samego kodu, z tym wyjątkiem, że nie tworzę indeksu nieklastrowanego w widoku.
Nie tworzę też obiektu statystycznego. Jeśli śledzisz i używasz programu SQL Server Management Studio (SSMS), aby wprowadzić poniższy kod, powinieneś być świadomy, że mogą pojawić się pewne czerwone linie - które wyglądają jak błędy. Nie są to (prawdopodobnie) błędy, ale dotyczą problemu z intellisense.
Możesz albo wyłączyć intellisense, albo po prostu zignorować błędy i uruchomić polecenia. Powinny zostać wypełnione bez błędów.
Następujący plan wykonania (bez widoku / widoku indeksu) jest tworzony po uruchomieniu następującego zapytania dla tabeli:
Daje to podstawę do porównania. Zauważ, że po zakończeniu zapytania utworzono obiekt statystyki (_WA_Sys_00000003_1FCDBCEB). Obiekt statystyki PK_PersistedViewTest został utworzony podczas tworzenia indeksu tabeli klastrowej.
Następnie tworzony jest filtrowany widok i indeks klastrowy w tym widoku:
Teraz spróbujmy ponownie uruchomić zapytanie, ale tym razem w widoku:
Nowy plan wykonania jest teraz:
Jeśli wierzyć nowemu planowi, po dodaniu widoku i indeksu klastrowego w tym widoku statystyki wydają się wskazywać, że czas wymagany do wykonania zapytania podwoił się. Zauważ też, że po uruchomieniu zapytania nie został utworzony nowy obiekt statystyczny do obsługi nowego indeksu, który różni się od zapytania w tabeli.
Plan zapytań nadal sugeruje, że utworzenie nieklastrowanego indeksu byłoby bardzo pomocne w poprawie wydajności zapytania. Czy to oznacza, że do widoku należy dodać indeks nieklastrowany, aby uzyskać pożądaną poprawę wydajności? Jest jeszcze jedna ostatnia rzecz do wypróbowania. Zmodyfikuj zapytanie, aby użyć opcji „WITH NOEXPAND”:
Powoduje to następujący plan zapytań:
Ten plan wykonania wygląda dość podobnie do tego, który został utworzony z indeksem nieklastrowanym podanym w odpowiedzi Maxa Vernona. Ale ten jest wykonywany z jednym mniejszym (nieklastrowanym) indeksem i jednym mniejszym obiektem statystycznym.
Okazuje się, że opcji NOEXPAND należy używać z ekspresową i standardową wersją SQL Server, aby właściwie wykorzystać widok indeksowany. Paul White ma znakomity artykuł, który wyjaśnia korzyści płynące z używania opcji NOEXPAND. Zaleca także, aby tę opcję stosować z wersją Enterprise, aby zapewnić, że optymalizator zastosuje gwarancję unikalności zapewnianą przez indeksy widoków.
Powyższą analizę wykonano z ekspresową wersją SQL Sever 2014. Próbowałem również z edycją programistyczną SQL Server 2016. Opcja NOEXPAND nie wydaje się być wymagana w przypadku wersji rozwojowej do osiągnięcia wzrostu wydajności, ale nadal jest zalecana .
Niecałe 5 miesięcy temu Microsoft udostępnił wersje programistyczne za darmo . Licencja ogranicza użycie wyłącznie do programowania, co oznacza, że bazy danych nie można używać w środowisku produkcyjnym. Tak więc, jeśli chciałeś przetestować tabele zoptymalizowane pod kątem pamięci, szyfrowanie, R itp., Nie masz już wymówki bez licencji. Z powodzeniem zainstalowałem go na moim komputerze kilka dni temu obok SQL Server 2014 Express bez żadnych problemów.
źródło