(Question déplacée de SO)
J'ai une table (données fictives) avec un index cluster contenant 2 colonnes:
Maintenant, je lance ces deux requêtes:
declare
@productid int =1 ,
@priceid int = 1
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid OR @productid IS NULL)
AND (priceid = @priceid OR @priceid IS NULL)
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid)
AND (priceid = @priceid)
Le plan d'exécution réel pour les deux requêtes est le suivant:
Comme vous pouvez le voir, le premier utilise SCAN tandis que le second utilise SEEK.
Cependant - en ajoutant OPTION (RECOMPILE)
à la première requête, le plan d'exécution a également utilisé SEEK:
Des amis du chat DBA m'ont dit que:
Dans votre requête, @ productid = 1, ce qui signifie que (productID = @ productID OU @productID IS NULL) peut être simplifié en (productID = @ productID). Le premier nécessite une analyse pour fonctionner avec n'importe quelle valeur de @productID, le second pourrait utiliser une recherche. Ainsi, lorsque vous utilisez RECOMPILE, SQL Server examinera la valeur que vous avez réellement dans @productID et fera le meilleur plan pour cela. Avec une valeur non nulle dans @productID, une recherche est la meilleure. Si la valeur de @productID est inconnue, le plan doit correspondre à toute valeur possible dans @productID, ce qui nécessiterait une analyse. Soyez averti: OPTION (RECOMPILE) forcera une recompilation du plan chaque fois que vous l'exécuterez, ce qui ajoutera quelques millisecondes à chaque exécution. Bien que ce ne soit un problème que si la requête s'exécute très fréquemment.
Aussi :
Si @productID est null, à quelle valeur rechercheriez-vous? Réponse: il n'y a rien à chercher. Toutes les valeurs sont éligibles.
Je comprends que OPTION (RECOMPILE)
SQL Server force à voir quelles sont les valeurs réelles des paramètres et à voir s'il peut RECHERCHER avec.
Mais maintenant, je perds l'avantage de la compilation anticipée.
Question
IMHO - SCAN ne se produira que si un paramètre est nul.
C'est bien - laissez SQL SERVER créer un plan d'exécution pour SCAN.
MAIS si SQL Server voit que j'exécute cette requête plusieurs fois avec des valeurs:, 1,1
alors pourquoi ne crée-t-il PAS UN AUTRE plan d'exécution et utilise SEEK pour cela?
AFAIK - SQL crée un plan d'exécution pour les requêtes les plus consultées .
Pourquoi SQL SERVER n'enregistre-t-il pas un plan d'exécution pour:
@productid int =1 , @priceid int = 1
(Je l'exécute plusieurs fois avec ces valeurs)
- Est-il possible de forcer SQL à conserver ce plan d'exécution (qui utilise SEEK) - pour une invocation future?