SELECT *
FROM …
WHERE @bar = 'BAR'
AND foo IN ('FOO', 'BAR', 'BAZ')
UNION ALL
SELECT *
FROM …
WHERE @bar = 'BAZ'
AND foo IN ('FOOBAR', 'FOOBAZ')
Ce sera le plus efficace indice.
SQL Server
va simplement optimiser l'une des requêtes, en fonction de la valeur de @bar
, et utilisera l'index sur foo
pour exécuter la requête restante.
Mise à jour:
Tableau master
a 20,000,000
enregistrements avec 2,000,000
enregistrements ayant name = 't'
.
Cette requête:
DECLARE @s INT
SET @s = 2
SELECT *
FROM master
WHERE (@s = 1 AND name IN ('t')) OR
(@s = 2 AND name IN ('zz'))
utilise un et ne retourne rien en 4
secondes:
|--Parallelism(Gather Streams)
|--Index Scan(OBJECT:([test].[dbo].[master].[ix_name_desc]), WHERE:([@s]=(1) AND [test].[dbo].[master].[name]='t' OR [@s]=(2) AND [test].[dbo].[master].[name]='zz'))
Cette requête:
DECLARE @s INT
SET @s = 2
SELECT *
FROM master
WHERE @s = 1 AND name IN ('t')
UNION ALL
SELECT *
FROM master
WHERE @s = 2 AND name IN ('zz')
utilise CONCATENATION
de deux requêtes distinctes (l'une des les étant en cours d'optimisation), et revient instantanément:
|--Concatenation
|--Parallelism(Gather Streams)
| |--Filter(WHERE:(STARTUP EXPR([@s]=(1))))
| |--Index Seek(OBJECT:([test].[dbo].[master].[ix_name_desc]), SEEK:([test].[dbo].[master].[name]='t') ORDERED FORWARD)
|--Filter(WHERE:(STARTUP EXPR([@s]=(2))))
|--Index Seek(OBJECT:([test].[dbo].[master].[ix_name_desc]), SEEK:([test].[dbo].[master].[name]='zz') ORDERED FORWARD)
Ce n'est pas la perte 'qui a été mon deuxième taux de frappe. –