この回答によれば、制限に使用される列にインデックスが構築されない限り、クエリはインデックスの恩恵を受けません。
私にはこの定義があります:
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
このクエリ:
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());
実際のプランを確認しましたが、述語と同じようにインデックスシークが1つだけありWHERE
ます- LastAccessTime
インデックスの一部ではなく、インデックスに「含まれる」だけの追加の「ブックマークルックアップ」はありません。
この動作は、列が単に「含まれる」のではなく、インデックスの一部でなければならないという規則に矛盾するように思えます。
私が観察した行動は正しいものですか?WHERE
含まれている列からの利益があるかどうか、または列をインデックスの一部にする必要があるかどうかを事前に知るにはどうすればよいですか?
(ItemState, CreationTime) INCLUDE (LastAccessTime)
(a,b)
のクエリはクエリでの使用には最適ではなく、SELECT a FROM t WHERE b=5;
オンのインデックス(b) INCLUDE (a)
ははるかに優れていると言われています。
ItemState
値に基づいてシークすることはできますが、シークは、インデックスが次のように構成されている場合ほど効率的ではありません(ItemState, CreationTime, LastAccessTime)