Mam utrwaloną kolumnę obliczeniową na stole, która jest po prostu złożona z połączonych kolumn, np
CREATE TABLE dbo.T
(
ID INT IDENTITY(1, 1) NOT NULL CONSTRAINT PK_T_ID PRIMARY KEY,
A VARCHAR(20) NOT NULL,
B VARCHAR(20) NOT NULL,
C VARCHAR(20) NOT NULL,
D DATE NULL,
E VARCHAR(20) NULL,
Comp AS A + '-' + B + '-' + C PERSISTED NOT NULL
);
W tym Compnie jest unikalny, a D jest prawidłowy od daty każdej kombinacji A, B, C, dlatego używam następującego zapytania, aby uzyskać datę końcową dla każdej A, B, C(w zasadzie następnej daty początkowej dla tej samej wartości Comp):
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = t1.Comp
AND t2.D > t1.D
ORDER BY t2.D
)
FROM dbo.T t1
WHERE t1.D IS NOT NULL -- DON'T CARE ABOUT INACTIVE RECORDS
ORDER BY t1.Comp;
Następnie dodałem indeks do kolumny obliczanej, aby pomóc w tym zapytaniu (i innych):
CREATE NONCLUSTERED INDEX IX_T_Comp_D ON dbo.T (Comp, D) WHERE D IS NOT NULL;
Plan zapytania mnie jednak zaskoczył. Pomyślałbym, że skoro mam klauzulę where stwierdzającą to D IS NOT NULLi sortuję według Comp, i nie odnoszę się do żadnej kolumny poza indeksem, to że indeks w kolumnie obliczeniowej może być użyty do skanowania t1 i t2, ale widziałem indeks klastrowany skandować.

Zmusiłem więc użycie tego indeksu, aby sprawdzić, czy przyniósł lepszy plan:
SELECT t1.ID,
t1.Comp,
t1.D,
D2 = ( SELECT TOP 1 t2.D
FROM dbo.T t2
WHERE t2.Comp = t1.Comp
AND t2.D > t1.D
ORDER BY t2.D
)
FROM dbo.T t1 WITH (INDEX (IX_T_Comp_D))
WHERE t1.D IS NOT NULL
ORDER BY t1.Comp;
Co dało ten plan

To pokazuje, że używane jest wyszukiwanie klucza, którego szczegółami są:

Teraz, zgodnie z dokumentacją SQL-Server:
Można utworzyć indeks w kolumnie obliczanej, która jest zdefiniowana za pomocą deterministycznego, ale nieprecyzyjnego wyrażenia, jeśli kolumna jest oznaczona jako PERSISTED w instrukcji CREATE TABLE lub ALTER TABLE. 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. Ta opcja umożliwia utworzenie indeksu w kolumnie obliczeniowej, gdy aparat bazy danych nie może dokładnie udowodnić, czy funkcja zwracająca wyrażenia w kolumnie obliczeniowej, w szczególności funkcja CLR utworzona w .NET Framework, jest zarówno deterministyczna, jak i precyzyjna.
Jeśli więc, jak mówią doktorzy: „ Aparat baz danych przechowuje obliczone wartości w tabeli” , a wartość jest również przechowywana w moim indeksie, dlaczego wymagane jest wyszukiwanie klucza, aby uzyskać A, B i C, gdy nie ma w nich odwołania zapytanie w ogóle? Zakładam, że są one używane do obliczania Comp, ale dlaczego? Ponadto, dlaczego zapytanie może korzystać z indeksu na t2, ale nie na t1?
Uwaga: otagowałem SQL Server 2008, ponieważ jest to wersja, na której jest mój główny problem, ale otrzymuję to samo zachowanie w 2012 roku.






