パラメータ化されたクエリの場合、2つのシークを実行することはできません
WHERE A=@P1 AND B=@P2 AND C=@P3 AND D=@P5
そして
WHERE A=@P1 AND B=@P2 AND C=@P4 AND D=@P5
なぜなら、@P3 = @P4
それが重複した行を誤って戻すからです。したがって、最初に重複を削除する演算子が必要になります。
簡単なテストから、この目的は、それが得られるかどうかに関係なく、テーブルのサイズに依存しているように見えます。以下のテストでは、245
/ 246
行はプラン間のカットオフポイントです(これは、1ページにすべてが一致するインデックスと2つのリーフページとルートページになるインデックス間のカットオフポイントでもあります)。
CREATE TABLE T(A INT,B INT,C INT,D INT)
INSERT INTO T
SELECT TOP (245) 1,2,3,5
FROM master..spt_values v1
CREATE CLUSTERED INDEX IX ON T(A, B, C, D)
SELECT index_level,page_count, record_count
FROM sys.dm_db_index_physical_stats(db_id(),object_id('T'),1,NULL, 'DETAILED')
DECLARE @C1 INT = 3,
@C2 INT = 4
SELECT * FROM T WHERE A=1 AND B=2 AND (C=@C1 OR C=@C2) AND D=5
DROP TABLE T
1ページ/ 245行
この計画は、A=1 AND B=2
残余述語でシークしています(C=@C1 OR C=@C2) AND D=5
2リーフページ/ 246行
2番目の計画では、追加のオペレーターは@C1,@C2
、シークを実行する前に最初から重複を削除する責任があります。
実際範囲の間シークされる第二平面にシークA=1 AND B=2 AND C > Expr1010
し、A=1 AND B=2 AND C < Expr1011
上の残留述語とD=5
。それでも、4つの列すべてに対する平等シークではありません。追加の計画演算子の詳細については、こちらをご覧ください。
追加OPTION (RECOMPILE)
すると、コンパイル時に重複するパラメータ値を検査して、2つの等価シークを含む計画を作成できます。
あなたもそれを達成することができます
;WITH CTE
AS (SELECT DISTINCT ( C )
FROM (VALUES (@C1),
(@C2)) V(C))
SELECT CA.*
FROM CTE
CROSS APPLY (SELECT *
FROM T
WHERE A=1 AND B=2 AND D=5 AND C = CTE.C) CA
ただし、実際にはこのテストケースでは、1つではなく2つのシークを1つのページインデックスに求めることで論理IOが増加するため、逆効果になる可能性があります。
OPTION (RECOMPILE)
ますか?