J'ai rencontré une situation étrange où l'ajout de OPTION (RECOMPILE)
à ma requête la fait s'exécuter en une demi-seconde, alors que si je l'omets, la requête prend bien plus de cinq minutes.
C'est le cas lorsque la requête est exécutée depuis Query Analyzer ou depuis mon programme C# via SqlCommand.ExecuteReader()
. Appeler (ou ne pas appeler) DBCC FREEPROCCACHE
o DBCC dropcleanbuffers
ne fait aucune différence ; les résultats des requêtes sont toujours renvoyés instantanément avec OPTION (RECOMPILE)
et plus de cinq minutes sans. La requête est toujours appelée avec les mêmes paramètres [pour les besoins de ce test].
J'utilise SQL Server 2008.
Je suis assez à l'aise avec l'écriture du SQL mais je n'ai jamais utilisé un OPTION
dans une requête et je n'étais pas familier avec le concept de cache de plan jusqu'à ce que je consulte les messages sur ce forum. D'après ce que j'ai lu dans ces messages, j'ai compris que OPTION (RECOMPILE)
est une opération coûteuse. Elle crée apparemment une nouvelle stratégie de recherche pour la requête. Alors pourquoi les requêtes ultérieures qui omettent l'élément OPTION (RECOMPILE)
sont si lents ? Les requêtes suivantes ne devraient-elles pas utiliser la stratégie de recherche calculée lors de l'appel précédent, qui comprenait l'indice de recompilation ?
Est-il très rare d'avoir une requête qui nécessite un indice de recompilation à chaque appel ?
Désolé pour cette question de base, mais je n'arrive pas à comprendre ce qui se passe.
UPDATE : On m'a demandé de poster la requête...
select acctNo,min(date) earliestDate
from(
select acctNo,tradeDate as date
from datafeed_trans
where feedid=@feedID and feedDate=@feedDate
union
select acctNo,feedDate as date
from datafeed_money
where feedid=@feedID and feedDate=@feedDate
union
select acctNo,feedDate as date
from datafeed_jnl
where feedid=@feedID and feedDate=@feedDate
)t1
group by t1.acctNo
OPTION(RECOMPILE)
Lorsque j'exécute le test à partir de Query Analyzer, je fais précéder les lignes suivantes :
declare @feedID int
select @feedID=20
declare @feedDate datetime
select @feedDate='1/2/2009'
Lorsque je l'appelle à partir de mon programme C#, les paramètres sont transmis par l'intermédiaire de la fonction SqlCommand.Parameters
propriété.
Pour les besoins de cette discussion, vous pouvez supposer que les paramètres ne changent jamais, ce qui nous permet d'exclure la cause d'un reniflement sous-optimal des paramètres.
4 votes
Quels sont les paramètres de la requête ? Consultez cet article. blogs.msdn.com/b/turgays/archive/2013/09/10/ Fondamentalement, SQL tente de générer le plan de requête en fonction des paramètres lors de la première compilation de la proc. Il peut générer un plan qui n'est pas optimal lorsque vous commencez à passer des paramètres différents, éventuellement plus réalistes.
3 votes
La requête est-elle assez concise pour être listée ici ? Je pense que Sparky a raison et que c'est probablement lié au reniflage des paramètres. J'ai eu un problème similaire qui m'a déconcerté jusqu'à la lecture de cet excellent article : sommarskog.se/query-plan-mysteries.html
1 votes
Mais dans ce cas (pour les besoins de ce test), je passe toujours les mêmes paramètres. Aucune autre application n'a pu se faufiler et appeler la requête en utilisant d'autres paramètres. Merci pour ces articles. Je vais les revoir.
2 votes
Cela peut se produire soit parce qu'il renifle les valeurs des paramètres et des variables, soit parce qu'il effectue des simplifications plus importantes. Des exemples de simplifications plus importantes seraient de réduire
X = @X OR @X IS NULL
aX=@X
et effectuer une recherche Voir ici o pousser les prédicats plus bas contre une vue avec des fonctions de fenêtre4 votes
Suite à votre modification, l'exemple de Query Analyzer utilise des variables et non des paramètres. La valeur de ces derniers n'est jamais reniflée sauf avec
RECOMPILE
. Dans tous les cas, saisissez les plans d'exécution et examinez les différences.