Pour une requête paramétrée Il ne peut pas simplement faire deux recherches sur
WHERE A=@P1 AND B=@P2 AND C=@P3 AND D=@P5
et
WHERE A=@P1 AND B=@P2 AND C=@P4 AND D=@P5
Parce @P3 = @P4
que si cela ramènerait incorrectement des lignes en double. Il faudrait donc un opérateur qui supprime les doublons de ceux-ci en premier.
D'après un test rapide à cette fin, il semble dépendre de la taille de la table, que vous l'obteniez ou non. Dans le test ci 245
- dessous / 246
rangées se trouve le point de coupure entre les plans (c'était aussi le point de coupure entre l'index s'adaptant le tout sur une seule page et devenant 2 pages feuilles et une page racine).
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 pages / 245 lignes
Ce plan a une recherche sur A=1 AND B=2
avec un prédicat résiduel sur(C=@C1 OR C=@C2) AND D=5
Pages 2 feuilles / 246 lignes
Dans le second plan, les opérateurs supplémentaires sont responsables de la suppression des doublons @C1,@C2
avant d'effectuer les recherches.
La recherche dans le deuxième plan est en fait une recherche de plage entre A=1 AND B=2 AND C > Expr1010
et A=1 AND B=2 AND C < Expr1011
avec un prédicat résiduel activé D=5
. Ce n'est toujours pas une recherche d'égalité sur les 4 colonnes. Pour plus d'informations sur les opérateurs de plans supplémentaires, cliquez ici .
L'ajout OPTION (RECOMPILE)
lui permet d'inspecter les valeurs des paramètres pour les doublons au moment de la compilation et produit un plan avec deux recherches d'égalité.
Vous pouvez également y parvenir avec
;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
Mais en réalité, dans ce cas de test, il serait probablement contre-productif, car avoir deux recherches dans l'index d'une seule page plutôt qu'une seule augmente le nombre d'entrées / sorties logiques.
OPTION (RECOMPILE)
?