テーブルRetailer_Relationsには、次の複合PKインデックスと推奨インデックスがあります。
欠落しているインデックスは役に立ち、間違いなく機能しますが、欠落しているインデックスにはあまり時間をかけません。これらのヒントは、実際の実行プランではなく、推定実行プランに基づいて作成されます。
より正確には、これらのインデックスヒントは、プランでオペレーターが使用するQuery Bucks™のコストを削減するという前提に基づいています。オプティマイザーは推定コストを計算し、それに応じて欠落しているインデックスヒントを追加します。
その結果、それらは非常に間違っている可能性があります。効果があるかどうかわからない場合は、前後の状況をテストすることをお勧めします。これを行うにはSET STATISTICS IO, TIME ON;
、クエリを実行する前にステートメントを追加
します。
また、statisticsparserを使用して、これらの統計を読みやすくすることもできます。
これは、インデックス内の列の順序が原因である可能性がありますか?
正解です。たとえば、クエリが次のようになっている場合、欠落しているインデックスを作成するとクエリの選択性が向上します。
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
またはこのように:
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
この背後にある理由は、両方のインデックスがRetailerIDでシークできるため、その部分は変更されないためです。しかし、RelationTypeに追加のフィルター/順序付けが適用されるとどうなりますか?それは、2番目のキー値ではなく3番目のキー値であるため、クラスター化インデックス内のあちこちにあります。そして、私たちが知っているように、これはNCIの2番目の重要な値です。
わかりましたが、非クラスター化インデックスはいつ、どのようにクエリを改善しますか?
いくつかのケースが考えられます:
- relationTypeが多くの値をフィルタリングする場合、残余I / Oが高くなり、非クラスター化インデックスが必要になる可能性があります(クエリ#1)
- 2つの列の順序付けが行われ(一方向)、結果セットが大きくなります(クエリ#2)。
- @AaronBertrandが述べたように:NCIと比較したCIサイズの違いがかなりの量である場合、NCIを追加すると、その恩恵を受けるクエリによって読み取られるページが減少します。
NCIサイドノート
補足として、CIキー列はすべての非クラスター化インデックスに自動的に含まれるため、NCIのインクルードリストにキー列を追加する必要はありません。
クラスタ化インデックスが同じままかどうかが不明で、列が常に含まれるようにする場合は、そうすることを選択できます。
クエリ自体については、PasteThePlanを介して実行プランを追加した場合、クエリの インデックス作成/改善に関する詳細情報を提供できます。
テスト中
テーブルを作成していくつかの行を追加する
CREATE TABLE Retailer_Relations (
RetailerID int ,
RelatedRetailerID int ,
RelationType smallint,
CreatedOn datetime,
CONSTRAINT PK_Retailer_Relations
PRIMARY KEY CLUSTERED (
RetailerID ASC,
RelatedRetailerID ASC,
RelationType ASC
) ON [PRIMARY])
DECLARE @I Int = 1
WHILE @I < 1000
BEGIN
INSERT INTO Retailer_Relations(RetailerID,RelatedRetailerID,RelationType,CreatedOn)
VALUES(@I,@I,@I,GETDATE()
)
set @I += 1
END
クエリ#1
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
インデックスなしのプランはこちら
シークを行っている間、RetailerIDでシークを行っています。その後、RelationTypeに残りのI / O述語を発行します
インデックスを追加
CREATE NONCLUSTERED INDEX IX_TEST
ON Retailer_Relations (
RetailerID,
RelationType
)
INCLUDE (
RelatedRetailerID
)
残りの述語はなくなり、すべてがシーク述語の両方の列で発生します。
実行計画
2番目のクエリでは、追加されたインデックスの有用性がさらに明らかになります。
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
インデックスなしでソート演算子を使用して計画します。
インデックスを使用して計画し、インデックスを使用して並べ替え演算子を削除する