J'ai un processus ETL qui implique une procédure stockée qui fait un usage intensif de SELECT INTO
instructions (minimalement enregistrées et donc plus rapides car elles génèrent moins de trafic de journaux). Parmi le lot de travaux qui a lieu dans une procédure stockée particulière, plusieurs des opérations les plus coûteuses sont des bobines désireuses qui semblent simplement mettre en mémoire tampon les résultats de la requête, puis les copier dans la table en cours de création.
La documentation MSDN sur bobines enthousiastes est assez clairsemée. Quelqu'un a-t-il une idée plus approfondie de savoir si elles sont vraiment nécessaires (et dans quelles circonstances)? J'ai quelques théories qui peuvent ou non avoir un sens, mais je n'ai pas réussi à les éliminer des requêtes.
Les fichiers .sqlplan sont assez volumineux (160 Ko), donc je suppose qu'il n'est probablement pas raisonnable de les publier directement sur un forum.
Voici donc quelques théories qui peuvent se prêter à des réponses spécifiques:
Ma compréhension de la mise en file d'attente est que c'est un peu un frein à votre plan d'exécution. Oui, cela représente une grande partie du coût de votre requête, mais il s'agit en fait d'une optimisation que SQL Server entreprend automatiquement afin d'éviter de nouvelles analyses coûteuses. Si vous évitiez la mise en file d'attente, le coût de l'arborescence d'exécution sur laquelle il se trouve va augmenter et presque certainement le coût de la requête entière augmenterait. Je n'ai aucune idée particulière de ce qui pourrait en particulier amener l'optimiseur de requêtes de la base de données à analyser l'exécution de cette manière, en particulier sans voir le code SQL, mais vous feriez probablement mieux de faire confiance à son comportement.
Cependant, cela ne signifie pas que votre plan d'exécution ne peut pas être optimisé, selon exactement ce que vous faites et la volatilité de vos données source. Lorsque vous faites un SELECT INTO
, vous verrez souvent des éléments de mise en file d'attente sur votre plan d'exécution, et cela peut être lié à l'isolement en lecture. Si cela convient à votre situation particulière, vous pouvez essayer de simplement abaisser le niveau d'isolement des transactions à quelque chose de moins coûteux et/ou utiliser l'indicateur NOLOCK
. J'ai trouvé dans des requêtes compliquées critiques en termes de performances que NOLOCK
, s'il est sûr et approprié pour vos données, peut augmenter considérablement la vitesse d'exécution des requêtes même s'il ne semble pas y avoir de raison.
Dans cette situation, si vous essayez READ UNCOMMITTED
ou l'astuce NOLOCK
, vous pourrez peut-être éliminer certains des spools. (Évidemment, vous ne voulez pas faire cela si cela risque de vous faire atterrir dans un état incohérent, mais les exigences d'isolement des données de chacun sont différentes). L'opérateur TOP
et l'opérateur OR
peuvent occasionnellement provoquer la mise en file d'attente, mais je doute que vous le fassiez dans un processus ETL ...
Vous avez raison de dire que vos FDU pourraient également être le coupable. Si vous n'utilisez chaque UDF qu'une seule fois, ce serait une expérience intéressante d'essayer de les mettre en ligne pour voir si vous obtenez un gros avantage en termes de performances. (Et si vous ne parvenez pas à trouver un moyen de les écrire en ligne avec la requête, c'est probablement la raison pour laquelle ils peuvent provoquer une mise en file d'attente).
Une dernière chose que je regarderais est que, si vous effectuez des jointures qui peuvent être réorganisées, essayez d'utiliser un indice pour forcer l'ordre de jointure à se produire dans ce que vous savez être l'ordre le plus sélectif. C'est un peu une portée mais ça ne fait pas de mal de l'essayer si vous êtes déjà bloqué en optimisation.