Secondo questa risposta , a meno che non venga creato un indice sulle colonne utilizzate per limitare, la query non beneficerà di un indice.
Ho questa definizione:
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
e questa query:
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());
Ho rivisto il piano reale e c'è solo una ricerca dell'indice con il predicato esattamente come nel WHERE
- nessuna "ricerca di segnalibri" aggiuntiva da recuperare LastAccessTime
anche se quest'ultimo è solo "incluso" nell'indice, non parte dell'indice.
Mi sembra che questo comportamento contraddica la regola secondo cui la colonna deve far parte dell'indice e non solo "inclusa".
Il comportamento che osservo è quello giusto? Come posso sapere in anticipo se i miei WHERE
vantaggi da una colonna inclusa o se la colonna fa parte dell'indice?
(ItemState, CreationTime) INCLUDE (LastAccessTime)
(a,b)
non è il migliore per una query con SELECT a FROM t WHERE b=5;
e che un indice attivo (b) INCLUDE (a)
è molto meglio.
ItemState
valore, tuttavia la ricerca non sarà efficiente come se il tuo indice fosse strutturato come segue(ItemState, CreationTime, LastAccessTime)