Según esta respuesta , a menos que se construya un índice sobre las columnas que se usan para restringir, la consulta no se beneficiará de un índice.
Tengo esta definición:
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
y esta consulta:
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());
Revisé el plan real, y solo hay una búsqueda de índice con el predicado exactamente como en el WHERE
- no hay "búsquedas de marcadores" adicionales para recuperar LastAccessTime
a pesar de que este último solo está "incluido" en el índice, no es parte del índice.
Me parece que este comportamiento contradice la regla de que la columna debe ser parte del índice, y no solo "incluida".
¿El comportamiento que observo es el correcto? ¿Cómo puedo saber de antemano si mis WHERE
beneficios de una columna incluida o si la columna forma parte del índice?
(ItemState, CreationTime) INCLUDE (LastAccessTime)
(a,b)
no es el mejor para una consulta SELECT a FROM t WHERE b=5;
y que un índice activado (b) INCLUDE (a)
es mucho mejor.
ItemState
valor, sin embargo, Seek no será tan eficiente como si su índice estuviera estructurado de la siguiente manera(ItemState, CreationTime, LastAccessTime)