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.


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.


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.


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:

...

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.