Tworzenie niesklastrowanego indeksu na nietrwałym wyliczonym SQL Server Column

10

Usiłuję znaleźć jakąkolwiek dokumentację dotyczącą tego, jak SQL Server faktycznie przechowuje nietrwałą kolumnę obliczeniową.

Weź następujący przykład:

--SCHEMA
CREATE TABLE dbo.Invoice
(
    InvoiceID INT IDENTITY(1, 1) PRIMARY KEY,
    CustomerID INT FOREIGN KEY REFERENCES dbo.Customer(CustomerID),
    InvoiceStatus NVARCHAR(50) NOT NULL,
    InvoiceStatusID AS CASE InvoiceStatus 
                         WHEN 'Sent' THEN 1 
                         WHEN 'Complete' THEN 2
                         WHEN 'Received' THEN 3
                       END
)
GO

--INDEX
CREATE NONCLUSTERED INDEX IX_Invoice ON Invoice
(
    CustomerID ASC
)
INCLUDE
(
    InvoiceStatusID
)
GO

Rozumiem, że jest przechowywany na poziomie liścia, ale jeśli wartość nie zostanie utrwalona, ​​w jaki sposób w ogóle coś jest przechowywane? W jaki sposób indeks pomaga SQL Serverowi znaleźć te wiersze w tej sytuacji?

Każda pomoc bardzo doceniana,

Wielkie dzięki,

EDYTOWAĆ:

Dzięki Brentowi i Aaronowi za odpowiedź na to pytanie , oto PasteThePlan wyraźnie pokazujący, co wyjaśnili.

Uberzen1
źródło
5
Nie jest utrwalany na stronach danych tabeli, ale jest utrwalany na stronach indeksu .
Aaron Bertrand
Nie utrwalone Kolumny obliczane nie są fizycznie przechowywane w tabeli. Są to wirtualne kolumny. Ich wartości są ponownie obliczane za każdym razem, gdy są przywoływane w zapytaniu. zobacz ten ref .
Kin Shah

Odpowiedzi:

11

Kiedy SQL Server tworzy indeks na polu obliczeniowym, pole obliczane jest zapisywane na dysk w tym czasie - ale tylko na stronach 8K tego indeksu. SQL Server może obliczyć InvoiceStatusID podczas odczytywania indeksu klastrowanego - nie ma potrzeby zapisywania tych danych w indeksie klastrowym.

Gdy usuwasz / aktualizujesz / wstawiasz wiersze w dbo.Faktura, dane w indeksach są aktualizowane. (Gdy zmienia się InvoiceStatus, SQL Server wie również o aktualizacji IX_Invoice.)

Najlepszym sposobem, aby to zobaczyć, jest zrobienie tego: utworzenie tych obiektów i wykonanie aktualizacji, które dotykają pola InvoiceStatusID. Opublikuj plan wykonania (PasteThePlan.com jest do tego pomocny), jeśli chcesz dowiedzieć się, gdzie mają miejsce aktualizacje indeksu.

Brent Ozar
źródło
1
@ Uberzen1 Nie, jak wyjaśnił, jest on zapisywany na stronach indeksu w czasie wstawiania / aktualizacji. Nie trzeba niczego przeliczać, jeśli indeks jest używany do uzyskania dostępu do kolumny.
Aaron Bertrand
Ach! Jestem teraz z tobą, przepraszam!
Uberzen1
6
@blobbles dobrze, bez obrazy, ale nie sądzę, że to na Brent. Mogą wkleić ten sam kod XML na dropbox, fora MSDN, tutaj, w zasadzie wszędzie w Internecie ... czy każda usługa online musi być teraz odpowiedzialna za tajemnice, które mogą zostać ujawnione przez ludzi, którzy przesyłają tam pliki?
Aaron Bertrand
2
@blobbles tak, po prostu nie możesz powstrzymać ludzi przed nadmiernym udostępnianiem. Hej, nawiasem mówiąc, śledź mnie na Instagramie - jestem BrentO - i udostępniam zdjęcia mojego śniadania. ;-)
Brent Ozar
4
@blobbles w linku Prywatność, stwierdza: Dane, które tu kopiujesz / wklejasz, są publiczne . Każdy może to przeczytać. Nie ma bezpieczeństwa.
ypercubeᵀᴹ
8

Wartość zindeksowanej, nietrwałej kolumny obliczeniowej nie jest utrwalana na stronach danych tabeli , ale jest utrwalana na stronach indeksu . Pozostaje nietrwały w tabeli, niezależnie od tego, czy jest utrwalony w 0, 1 czy w wielu indeksach.

Aby zilustrować opis Brenta, biorąc podany przez ciebie przykład, wstawmy wiersz:

INSERT dbo.Invoice(CustomerID, InvoiceStatus) VALUES(1,N'Sent');

Zobaczmy teraz strony indeksu:

DBCC TRACEON(3604, -1);
DBCC IND(N'dbname', N'dbo.Invoice', 2);

(Oczywiście zmieniają się dbname, a identyfikator indeksu może nie być w twoim przypadku 2).

Dane wyjściowe (twoje na pewno będą się różnić):

wprowadź opis zdjęcia tutaj

Na koniec sprawdźmy stronę pod kątem PageType2:

DBCC PAGE(7, 1, 584, 3);

(Prawdopodobnie będziesz musiał zmienić 7, aby dopasować identyfikator bazy danych, a jeśli masz wiele plików danych, może być konieczna zmiana drugiego argumentu, aby pasował PageFIDdo pierwszego wyniku).

Wynik:

wprowadź opis zdjęcia tutaj

To jest na stronie indeksu.

Aaron Bertrand
źródło
Bardzo fajnie, dzięki Aaron. Powodem, dla którego zadałem pytanie na początku, jest fakt, że mam poważne problemy z wdrożeniem podobnego indeksu w prawdziwym świecie i chciałem dokładnie zrozumieć, co się dzieje pod maską, abym mógł rozwiązać problem. To bardzo pomaga, dzięki!
Uberzen1
1
@ Uberzen1 Czy potrafisz zdefiniować „prawdziwy problem”? Czy zamierzasz opublikować pytanie dotyczące tego problemu?
Aaron Bertrand
Mogę to zrobić, najpierw chciałem to trochę zagłębić, ale po prostu chciałem się zastanowić, co dokładnie robi instrukcja tworzenia indeksu. TLDR jest; Mam dużą tabelę podobną do powyższej tabeli faktur, ma ona około 400 milionów rekordów i, niestety, kolumna OrderStatus uderzyła w środek, co sprawia, że ​​indeksowanie itp. Jest trochę bolesne. Na razie dodaliśmy kolumnę obliczoną, która ostatecznie będzie trwała i przeniesiemy pole varchar do jego własnej tabeli. 1/2
Uberzen1
5
@ Uberzen1 Tak, ponieważ kolumna obliczeniowa jest faktycznie zmaterializowana na dysku podczas zapisu do indeksu, cała ta aktywność musi zostać zarejestrowana. Obejściem może być przestanie polegać na kolumnie obliczeniowej - albo wstaw to wyrażenie do widoku, albo do zapytań ad hoc, a jeśli nie jest to opcja, możesz utworzyć nową kolumnę zerowalną, zaktualizować ją we fragmentach (aby uniknąć zabijania dziennika) , a następnie upuść kolumnę obliczoną, zmień nazwę nowej kolumny i zmień DML, aby ręcznie ją zapisać. Ale tak naprawdę, ponieważ są to zbędne informacje, które można uzyskać z istniejących danych, wybrałbym pierwszą opcję.
Aaron Bertrand
2
Dziękuję bardzo Aaron. Cieszę się, że wspomniałeś o postawieniu przed nim poglądu, ponieważ to też było moje rozwiązanie, być może nadszedł czas, aby ponownie przemyśleć ten pomysł!
Uberzen1
7

Atrybut PERSISTEDkolumny obliczanej odnosi się do tego, czy wartości są utrwalane w tabeli (indeks klastrowany lub sterta), a nie od tego, czy wartości są utrwalane w indeksie.

CREATE INDEXMa wymagań dotyczących ograniczeń dotyczących obliczonych kolumn i indeksów:

Kolumny obliczeniowe, które są deterministyczne i albo dokładne, albo nieprecyzyjne, mogą być kolumnami. Kolumny obliczone pochodzące z typów danych image, ntext, text, varchar (max), nvarchar (max), varbinary (max) i xml mogą być zawarte w kolumnach innych niż kluczowe, o ile typy danych kolumny obliczanej są dozwolone jako uwzględnione kolumna. Aby uzyskać więcej informacji, zobacz Indeksy dotyczące kolumn obliczanych.

Nie ma ograniczeń co do tego, czy kolumna obliczana jest utrwalona, ​​czy nie.

i dalej (nie o uwzględnionych, ale o obliczonych kolumnach w głównej części indeksu):

Indeksy można tworzyć na kolumnach obliczeniowych. Ponadto kolumny obliczane mogą mieć właściwość PERSISTED. Oznacza to, że Aparat baz danych przechowuje obliczone wartości w tabeli i aktualizuje je, gdy są aktualizowane inne kolumny, od których zależy obliczona kolumna. Aparat baz danych korzysta z tych utrwalonych wartości podczas tworzenia indeksu w kolumnie i do odwołania do indeksu w zapytaniu.

Aby zindeksować kolumnę obliczaną, kolumna obliczana musi (być) deterministyczna i precyzyjna. Jednak użycie tej PERSISTEDwłaściwości rozszerza typ indeksowanych kolumn obliczeniowych o:

...

ypercubeᵀᴹ
źródło