321行を含むテーブル(以下に作成)があります。
以下の最後のクエリでは、非クラスター化インデックスを使用してからキールックアップを使用することを期待しています。ただし、代わりにクラスター化インデックススキャンを使用します。期待どおり単一行のみが返されます。
非クラスター化インデックスを使用するのではなく、なぜスキャンを実行するのですか?テーブルに含まれているのは321行しかないためですか?
CREATE TABLE dbo.TestIndexSample
(
Code char(4) NOT NULL,
Name nvarchar(200) NOT NULL,
ModifiedDate datetime NOT NULL CONSTRAINT [DF_TestIndexSample_ModifiedDate] DEFAULT GETDATE(),
CONSTRAINT [PK_TestIndexSample_Code] PRIMARY KEY CLUSTERED(Code)
);
GO
CREATE NONCLUSTERED INDEX IX_TestIndexSample_Name
ON dbo.TestIndexSample(Name);
GO
INSERT INTO dbo.TestIndexSample(Code, Name)
select CodeName, FullName
from dbo.SourceTest
GO
SELECT * FROM dbo.TestIndexSample
SELECT * FROM dbo.TestIndexSample where Code = 'X132EY'
SELECT * FROM dbo.TestIndexSample where Name = 'User A'
SQL Serverで非クラスター化インデックスを使用するように強制できます。
SELECT Code, Name, ModifiedDate
FROM dbo.TestIndexSample WITH(INDEX (IX_TestIndexSample_Name))
WHERE Name = 'NAME10';
ヒントがないと、クエリオプティマイザはこの少量のデータに対してインデックスのあるプランをよりコストがかかると見なしますが、テーブルの行数を増やすことでこのプランを取得できます。私はなんとか600行でそれを達成しました:
SELECT Code, Name, ModifiedDate
FROM dbo.TestIndexSample
WHERE Name = 'NAME10';
dbfiddle ここ
インデックスシークのみを取得する場合、クエリはName
のみを返す必要があるため、データはインデックスからのみプルされます。
SELECT Name
FROM dbo.TestIndexSample
WHERE Name = 'NAME10';
ただし、他の列も返す必要がある場合は、カバリングインデックスを使用できます。
CREATE NONCLUSTERED INDEX IX_TestIndexSample_Name
ON dbo.TestIndexSample(Name) INCLUDE (Code, ModifiedDate);
当然、インデックスのサイズは増加しますが、この行数では何も重要ではありません。
これで、現在のクエリはインデックスシークを使用します。
SELECT Code, Name, ModifiedDate
FROM dbo.TestIndexSample
WHERE Name = 'NAME10';
テーブルに含まれているのは321行しかないためですか?
はいそれは原因であるはずです。
テーブルには何ページありますか?データページが1つしかない可能性が非常に高いため、クラスター化インデックススキャンは、サーバーが2ページだけを読み取ってこの作業を実行できることを意味します。
次のコードを使用してページ数を確認できます。
select index_id, total_pages
from sys.allocation_units au join sys.partitions p
on au.container_id = p.hobt_id
where p.object_id = object_id('dbo.TestIndexSample');
ここに index_id
= 1はクラスター化に対応し、index_id
= 2から非クラスター化インデックス。