According to this answer, unless an index is built over the columns which are used to restrict, the query will not benefit from an index.
I have this definition:
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
and this 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());
I reviewed the actual plan, and there's just one index seek with the predicate exactly as in the WHERE
- no additional "bookmark lookups" to retrieve LastAccessTime
even though the latter is only "included" into the index, not part of the index.
It looks to me like this behavior contradicts the rule that the column must be part of the index, and not just "included".
Is the behavior I observe the right one? How can I know in advance if my WHERE
benefits from an included column or needs the column to be part of the index?
ItemState
value, however the Seek will not be as efficient as if your Index was structured as follows(ItemState, CreationTime, LastAccessTime)
(ItemState, CreationTime) INCLUDE (LastAccessTime)
(a,b)
is not the best for a query withSELECT a FROM t WHERE b=5;
and that an index on(b) INCLUDE (a)
is much better.