このクエリでインデックススプールが使用されないのはなぜですか?


23

オプティマイザーの動作をよりよく理解し、インデックススプールの制限を理解するために、この質問をしています。ヒープに1〜10000の整数を入れると仮定します。

CREATE TABLE X_10000 (ID INT NOT NULL);
truncate table X_10000;

INSERT INTO X_10000 WITH (TABLOCK)
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

そして、ネストされたループ結合を強制しますMAXDOP 1

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID = b.ID
OPTION (LOOP JOIN, MAXDOP 1);

これは、SQL Serverに対して行うにはやや不親切なアクションです。両方のテーブルに関連するインデックスがない場合、ネストされたループ結合は多くの場合、良い選択ではありません。計画は次のとおりです。

悪いクエリ

私のマシンでは、テーブルスプールから100000000行がフェッチされ、クエリは13秒かかります。ただし、クエリを遅くする必要がある理由はわかりません。クエリオプティマイザーには、インデックススプールを使用してインデックスを即座に作成する機能があります。このクエリは、インデックススプールの完璧な候補のようです。

次のクエリは、最初のクエリと同じ結果を返し、インデックススプールを持ち、1秒未満で終了します。

SELECT *
FROM X_10000 a
CROSS APPLY (SELECT TOP (9223372036854775807) b.ID FROM X_10000 b WHERE a.ID = b.ID) ca
OPTION (LOOP JOIN, MAXDOP 1);

回避策1

このクエリにはインデックススプールもあり、1秒未満で終了します。

SELECT *
FROM X_10000 a
INNER JOIN X_10000 b ON a.ID >= b.ID AND a.ID <= b.ID
OPTION (LOOP JOIN, MAXDOP 1);

回避策2

元のクエリにインデックススプールがないのはなぜですか?インデックススプールを提供する文書化された、または文書化されていないヒントまたはトレースフラグのセットはありますか?私はこの関連する質問を見つけましたが、私の質問に完全に答えているわけではなく、このクエリで神秘的なトレースフラグを機能させることができません。

回答:


20

ご存知のように、オプティマイザーの検索は完全ではありません。コンテキストで意味があり、実際のクエリに対して頻繁に配当を支払うものを試みます。2つの単一列のインデックスなしヒープテーブル間でループ結合を強制することは、このようなシナリオではありません。ただし、詳細は次のとおりです。

SQL Serverは、結合に関するより多くのトリックを知っているため、変換を早期に適用することを好みます。後で、結合を適用に戻すことを検討する場合があります。相関する2つのパラメーターの違い(外部参照)。内側に適切なインデックスがある場合に適用されます。この例にはインデックスがないため、オプティマイザーは適用への変換を探求するように説得されません。

単純な(適用されない)結合には、外部参照の代わりに結合演算子の結合述部があります。非適用のスプール最適化は、通常、遅延テーブルスプールです。これは、内側に述語がなく、結合時にのみであるためです。

オプティマイザーは、適用を可能にするためにその場で索引を作成することを考慮しません。むしろ、イベントのシーケンスは通常逆です。つまり、適切なインデックスが存在するために適用する変換です。

APPLYクエリで構文を使用することにより、結合ではなく適用を奨励できる場合があります。文書化されていないトレースフラグ9114は、オプティマイザが論理的な適用を前もって結合に変換するのを思いとどまらせることにより、これを支援できます。例えば:

SELECT * 
FROM dbo.X_1000 AS a
CROSS APPLY (SELECT * FROM dbo.X_1000 AS b WHERE b.ID = a.ID) AS b
OPTION (QUERYTRACEON 9114);

スプール計画

外部参照は選択が結合の内側に適用されることを意味するため、インデックススプールは適用に適しています。これはよく表示されますがSelToIndexOnTheFly、他のパスが存在します。私の記事The Eager Index Spool and The Optimizerを参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.