Opération physique de concaténation: garantit-elle l'ordre d'exécution?

12

Dans SQL standard, le résultat d'un union alln'est pas garanti dans n'importe quel ordre. Donc, quelque chose comme:

select 'A' as c union all select 'B'

Pourrait retourner deux lignes dans n'importe quel ordre (bien que, dans la pratique sur n'importe quelle base de données que je connaisse, «A» précédera «B»).

Dans SQL Server, cela se transforme en un plan d'exécution utilisant une opération physique de "concaténation".

Je pourrais facilement imaginer que l'opération de concaténation balayerait ses entrées, renvoyant toutes les entrées disponibles. Cependant, j'ai trouvé la déclaration suivante sur le web ( ici ):

Le processeur de requêtes exécutera ce plan dans l'ordre dans lequel les opérateurs apparaissent dans le plan, le premier est le premier et le dernier est le dernier.

Question: est-ce vrai dans la pratique? Est-ce garanti que c'est vrai?

Je n'ai trouvé aucune référence dans la documentation Microsoft que les entrées sont analysées dans l'ordre, du premier au dernier. D'un autre côté, chaque fois que j'essaye de l'exécuter, les résultats suggèrent que les entrées sont, en effet, traitées dans l'ordre.

Existe-t-il un moyen pour que le moteur traite plus d'une entrée à la fois? Mes tests (utilisant des expressions beaucoup plus compliquées que des constantes) sont sur une machine à 8 cœurs activée en parallèle, et la plupart des requêtes profitent du parallélisme.

Gordon Linoff
la source

Réponses:

10

Non , il n'y a pas de documentation de Microsoft garantissant le comportement, il n'est donc pas garanti .

En outre, en supposant que l'article Simple Talk est correct et que l'opérateur physique de concaténation traite toujours les entrées dans l'ordre indiqué dans le plan (très probablement vrai), puis sans garantie que SQL Server générera toujours des plans qui gardent les mêmes l'ordre entre le texte de la requête et le plan de requête, vous n'êtes que légèrement mieux loti.

Nous pouvons cependant approfondir cette question. Si l'optimiseur de requête a pu réorganiser l'entrée d'opérateur de concaténation, il doit exister des lignes dans le DMV non documenté, sys.dm_exec_query_transformation_statscorrespondant à cette optimisation.

SELECT * FROM sys.dm_exec_query_transformation_stats 
    WHERE name LIKE '%CON%' OR name LIKE '%UNIA%'

Sur SQL Server 2012 Enterprise Edition, cela produit 24 lignes. En ignorant les fausses correspondances pour les transformations liées aux constantes, il existe une transformation liée à l'opérateur physique de concaténation UNIAtoCON(Union All to Concatenation). Ainsi, au niveau de l'opérateur physique, il apparaît qu'une fois qu'un opérateur de concaténation est sélectionné, il sera traité dans l'ordre de l'opérateur logique Union All dont il est dérivé.


En fait, ce n'est pas tout à fait vrai. Il existe des réécritures post-optimisation qui peuvent réorganiser les entrées vers un opérateur de concaténation physique une fois l'optimisation basée sur les coûts terminée. Un exemple se produit lorsque la concaténation est soumise à un objectif de ligne (il peut donc être important de lire d'abord à partir de l'entrée la moins chère). Voir UNION ALLOptimisation par Paul White pour plus de détails.

Cette réécriture physique tardive était fonctionnelle jusqu'à SQL Server 2008 R2 inclus, mais une régression signifiait qu'elle ne s'appliquait plus à SQL Server 2012 et versions ultérieures. Un correctif a été publié qui rétablit cette réécriture pour SQL Server 2014 et versions ultérieures (pas 2012) avec les correctifs de l'optimiseur de requête activés (par exemple, l'indicateur de trace 4199).


Mais à propos de l'opérateur Logical Union All ( UNIA)? Il y a une UNIAReorderInputstransformation, qui peut réorganiser les entrées. Il existe également deux opérateurs physiques qui peuvent être utilisés pour implémenter une Union logique UNIAtoCONet UNIAtoMERGE(Union All to Merge Union).

Il apparaît donc que l'optimiseur de requête peut réorganiser les entrées pour a UNION ALL; cependant, il ne semble pas s'agir d'une transformation courante (zéro utilisation de UNIAReorderInputssur les serveurs SQL que j'ai facilement accessible. Nous ne connaissons pas les circonstances qui pourraient faire que l'optimiseur soit utilisé UNIAReorderInputs; bien qu'il soit certainement utilisé lorsqu'un guide de plan ou une utilisation L'indice de plan est utilisé pour forcer un plan généré à l'aide des entrées physiques réordonnées de l'objectif de ligne mentionnées ci-dessus.

Existe-t-il un moyen pour que le moteur traite plus d'une entrée à la fois?

L'opérateur physique de concaténation peut exister dans une section parallèle d'un plan. Avec quelques difficultés, j'ai pu produire un plan avec des concaténations parallèles en utilisant la requête suivante:

SELECT userid, regdate  FROM (  --Users table is around 3mil rows
    SELECT  userid, RegDate FROM users WHERE userid > 1000000
    UNION 
    SELECT  userid, RegDate FROM users WHERE userid < 1000000
    UNION all
    SELECT userid, RegDate FROM users WHERE userid < 2000000
    ) d ORDER BY RegDate OPTION (RECOMPILE)

Ainsi, au sens strict, l'opérateur de concaténation physique semble toujours traiter les entrées de manière cohérente (première en haut, seconde en bas); cependant, l'optimiseur peut changer l'ordre des entrées avant de choisir l'opérateur physique ou utiliser une union de fusion au lieu d'une concaténation.

StrayCatDBA
la source
8

Selon Craig Freedman, l'ordre d'exécution de l'opérateur de concaténation est garanti.

De son article de blog Affichage des plans de requête sur les blogs MSDN:

Notez que lorsqu'un opérateur a plus d'un enfant, l'ordre des enfants est important. L'enfant le plus haut est le premier enfant tandis que l'enfant le plus bas est le deuxième. L'opérateur de concaténation traite les enfants dans cet ordre.

Et des livres en ligne Référence des opérateurs physiques et logiques Showplan

L'opérateur physique de concaténation a deux entrées ou plus et une sortie. La concaténation copie les lignes du premier flux d'entrée dans le flux de sortie, puis répète cette opération pour chaque flux d'entrée supplémentaire.

Mikael Eriksson
la source
Cette citation est assez proche de ce que je cherchais. Je suis prêt à passer du stade de l'exécution dans cet ordre au retour dans cet ordre - même s'il est décevant que la documentation empêche le traitement parallèle dans ce cas.
Gordon Linoff
2

Réponse du wiki communautaire :

Je ne sais pas si vous pouvez prouver que tout comportement observé est toujours garanti, d'une manière ou d'une autre, à moins que vous ne puissiez fabriquer un contre-exemple. En l'absence de cela, la manière de corriger l'ordre de retour des résultats est bien sûr d'ajouter un ORDER BY.

Je ne sais pas s'il existe un "correctif", ou s'il existe un besoin pour un correctif, si vous pouvez démontrer que dans certains scénarios, les requêtes sont traitées dans un ordre différent.

L'absence de documentation officielle explicite me suggère que vous ne devriez pas en dépendre. C'est exactement le genre de chose avec laquelle les gens ont eu des ennuis ORDER BYdans une vue et GROUP BYsans ORDER BY, il y a 8 ans, lorsque l'optimiseur de SQL Server 2005 a été publié.

Avec toutes les nouvelles fonctionnalités des nouvelles versions de SQL Server (avec d'autres à venir), même si vous pensez pouvoir garantir un comportement spécifique aujourd'hui, je ne m'attendrais pas à ce qu'il se vérifie (jusqu'à ce qu'il soit documenté pour le faire).

Même si vous ne dépendez pas de ce comportement, qu'allez-vous faire des résultats? Quoi qu'il en soit, je n'appellerais pas un article Simple Talk par un officiel extérieur . Pour tout ce que nous savons, ce n'est qu'une supposition basée sur l'observation.

Microsoft ne publiera jamais de documentation officielle disant que «x» n'est pas garanti pour faire «y». C'est l'une des raisons pour lesquelles nous avons encore, près d'une décennie plus tard, des difficultés à convaincre les gens qu'ils ne peuvent pas se fier à la commande observée sans ORDER BY- il n'y a aucune documentation qui déclare "ce n'est pas garanti".

utilisateur126897
la source