オプティマイザーの動作をよりよく理解し、インデックススプールの制限を理解するために、この質問をしています。ヒープに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秒未満で終了します。
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);
元のクエリにインデックススプールがないのはなぜですか?インデックススプールを提供する文書化された、または文書化されていないヒントまたはトレースフラグのセットはありますか?私はこの関連する質問を見つけましたが、私の質問に完全に答えているわけではなく、このクエリで神秘的なトレースフラグを機能させることができません。