Zgodnie z tą odpowiedzią , o ile indeks nie zostanie zbudowany na kolumnach służących do ograniczenia, zapytanie nie skorzysta z indeksu.
Mam tę definicję:
CREATE TABLE [dbo].[JobItems] (
[ItemId] UNIQUEIDENTIFIER NOT NULL,
[ItemState] INT NOT NULL,
[ItemPriority] INT NOT NULL,
[CreationTime] DATETIME NULL DEFAULT GETUTCDATE(),
[LastAccessTime] DATETIME NULL DEFAULT GETUTCDATE(),
-- other columns
);
CREATE UNIQUE CLUSTERED INDEX [JobItemsIndex]
ON [dbo].[JobItems]([ItemId] ASC);
GO
CREATE INDEX [GetItemToProcessIndex]
ON [dbo].[JobItems]([ItemState], [ItemPriority], [CreationTime])
INCLUDE (LastAccessTime);
GO
i to zapytanie:
UPDATE TOP (150) JobItems
SET ItemState = 17
WHERE
ItemState IN (3, 9, 10)
AND LastAccessTime < DATEADD (day, -2, GETUTCDATE())
AND CreationTime < DATEADD (day, -2, GETUTCDATE());
Przejrzałem aktualny plan i jest tylko jedno wyszukiwanie indeksu z predykatem dokładnie tak, jak w przypadku WHERE
- żadnych dodatkowych „wyszukiwań zakładek” do pobrania, LastAccessTime
nawet jeśli to ostatnie jest „uwzględnione” w indeksie, a nie jego części.
Wydaje mi się, że takie zachowanie jest sprzeczne z regułą, że kolumna musi być częścią indeksu, a nie tylko „uwzględniona”.
Czy zachowanie, które obserwuję, jest właściwe? Skąd mam wiedzieć z góry, czy moje WHERE
korzyści z dołączonej kolumny lub czy kolumna jest częścią indeksu?
(ItemState, CreationTime) INCLUDE (LastAccessTime)
(a,b)
nie jest najlepszy dla zapytania, SELECT a FROM t WHERE b=5;
a indeks na (b) INCLUDE (a)
jest znacznie lepszy.
ItemState
wartość, jednak szukanie nie będzie tak skuteczne, jak gdyby indeks miał następującą strukturę(ItemState, CreationTime, LastAccessTime)