La prise en charge de Parallel Scalar UDF est-elle une demande de fonctionnalité raisonnable?

10

Il est assez bien documenté que le scalaire UDF force un plan de série global.

Exécution de fonctions en parallèle

Étant donné un grand nombre de lignes arrivant à un point dans le pipeline où une FDU doit être calculée, pourquoi le moteur ne peut-il pas simplement les répartir entre les processeurs? S'il n'y a pas d'état dans un FDU, la commande ne devrait pas avoir d'importance.

Il existe des allégations selon lesquelles les FDU étant une boîte noire doivent utiliser le curseur. Je peux voir qu'un curseur utilisateur ne peut pas être parallélisé dans un SP pour les cas où un état est maintenu entre les itérations mais semble qu'il devrait être parallélisable sinon.

Points supplémentaires pour expliquer pourquoi le moteur force l'ensemble du plan à être en série au lieu de simplement l'étape de calcul UDF.

La prise en charge d'UDF parallèle est-elle une fonctionnalité raisonnable à demander?

crokusek
la source
1
La réaction appropriée semble être, comme indiqué dans la réponse acceptée à votre lien, de réécrire toutes les fonctions définies par l'utilisateur scalaire en tant que fonctions à valeur de table en ligne à colonne unique . Celles-ci sont développées de la même manière qu'une vue et sont donc entièrement optimisées. Dans cette perspective, votre question a-t-elle encore du mérite?
Pieter Geerkens
1
Oui en cas de succès avec la solution de contournement TVF. J'ai demandé car il semble faux d'éviter d'utiliser une telle construction naturelle. De plus, il semble peu pratique de s'attendre à ce que les nouveaux développeurs SQL apprennent les composants internes UDF.
crokusek
Commentaire clarifiant. Succès avec ITVF mais pas avec TVF multi-déclarations.
crokusek

Réponses:

17

Il est assez bien documenté que les FDU imposent un plan de série global.

Je ne suis pas certain que tout cela soit bien documenté.

  • Une fonction scalaire T-SQL empêche le parallélisme n'importe où dans le plan.
  • Une fonction scalaire CLR peut être exécutée en parallèle, tant qu'elle n'accède pas à la base de données.
  • Une fonction T-SQL multi-instructions de valeur table force une zone série dans un plan qui peut utiliser le parallélisme ailleurs.
  • Une fonction T-SQL de table en ligne est développée comme une vue, elle n'a donc aucun effet direct.

Voir Forcer un plan d'exécution parallèle et / ou la présentation Parallel Execution de Craig Freedman .

Certains prétendent que les FDU étant une boîte noire, il faut utiliser le curseur.

Ces affirmations ne sont pas correctes.

Points supplémentaires pour expliquer pourquoi le moteur force l'ensemble du plan à être en série au lieu de simplement l'étape de calcul UDF.

Je crois comprendre que les restrictions actuelles sont uniquement le résultat de certains détails de mise en œuvre. Il n'y a aucune raison fondamentale pour laquelle les fonctions ne peuvent pas être exécutées en utilisant le parallélisme.

Plus précisément, les fonctions scalaires T-SQL s'exécutent dans un contexte T-SQL distinct, ce qui complique considérablement le bon fonctionnement, la coordination et l'arrêt (en particulier en cas d'erreur).

De même, les variables de table prennent en charge les lectures parallèles (mais pas les écritures) en général, mais la variable de table exposée par une fonction table ne peut pas prendre en charge les lectures parallèles pour des raisons spécifiques à l'implémentation. Vous auriez besoin de quelqu'un avec un accès au code source (et la liberté de partager des détails) pour fournir une réponse faisant autorité, je le crains.

La prise en charge d'UDF parallèle est-elle une fonctionnalité raisonnable à demander?

Bien sûr, si vous pouvez faire un dossier suffisamment solide. Mon sentiment est que le travail impliqué serait considérable, donc votre proposition devrait répondre à une barre extrêmement élevée. Par exemple, une demande connexe (et beaucoup plus simple) de fournir des fonctions scalaires en ligne a un grand support, mais a langui sans mise en œuvre depuis des années maintenant.


Vous aimerez peut-être lire le document de Microsoft:

... qui décrit l'approche que Microsoft envisage d'adopter pour résoudre les problèmes de performances des fonctions scalaires T-SQL dans la version après SQL Server 2017.

L'objectif de Froid est de permettre aux développeurs d'utiliser les abstractions des FDU et des procédures sans compromettre les performances. Froid atteint cet objectif en utilisant une nouvelle technique pour convertir automatiquement les programmes impératifs en formes algébriques relationnelles équivalentes chaque fois que possible. Froid modélise des blocs de code impératif en tant qu'expressions relationnelles et les combine systématiquement en une seule expression à l'aide de l'opérateur Apply, permettant ainsi à l'optimiseur de requête de choisir des plans de requête parallèles efficaces orientés ensemble .

(c'est moi qui souligne)


Les fonctions scalaires T-SQL en ligne sont désormais implémentées dans SQL Server 2019 .

Paul White 9
la source
11

Comme Paul l'a mentionné à juste titre dans sa réponse, il n'y a aucune raison fondamentale pour laquelle les FDU scalaires ne pourraient pas être exécutés en utilisant le parallélisme. Cependant, en dehors des défis de mise en œuvre, il existe une autre raison pour les forcer à être en série. L' article de Froid cité par Paul donne plus d'informations à ce sujet.

Citant le document (section 2.3):

Actuellement, SQL Server n'utilise pas le parallélisme intra-requête dans les requêtes qui appellent des FDU. Des méthodes peuvent être conçues pour atténuer cette limitation, mais elles introduisent des défis supplémentaires, tels que le choix du bon degré de parallélisme pour chaque appel de l'UDF.

Par exemple, considérez une UDF qui invoque d'autres requêtes SQL, comme celle de la figure 1. Chacune de ces requêtes peut elle-même utiliser le parallélisme et, par conséquent, l'optimiseur n'a aucun moyen de savoir comment partager des threads entre elles, sauf s'il examine la UDF et décide du degré de parallélisme pour chaque requête à l'intérieur (qui pourrait potentiellement changer d'une invocation à une autre). Avec les UDF imbriqués et récursifs, ce problème devient encore plus difficile à gérer.

L'approche de Froid, telle que décrite dans le document, entraînera non seulement des plans parallèles, mais ajoutera également de nombreux autres avantages pour les requêtes avec des FDU. En substance, il subsume votre demande d'exécution parallèle d'UDF.

Mise à jour: Froid est désormais disponible en tant que fonctionnalité de l'aperçu de SQL Server 2019. Cette fonctionnalité est appelée "Inclusion de UDF scalaire". Plus de détails ici: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2018/11/07/introducing-scalar-udf-inlining/

[Divulgation: je suis co-auteur du papier Froid]

Karthik
la source
Très bien! Si je comprends bien, cela va convertir automatiquement l'UDF en ITVF en interne. Nous l'avions fait pour quelques-uns (w / déclare / if / else) et avons fait un joli bordel. Nous avons même eu une "colonne" de débogage.
crokusek
1
Il ne convertit pas réellement l'UDF en ITVF, mais votre intuition est correcte. Faire cela manuellement au niveau de la requête SQL est vraiment compliqué pour les FDU complexes. Froid fait cette transformation sur l'arbre d'algèbre relationnelle, ce qui évite le gâchis :)
Karthik
@Karthik pourriez-vous jeter un œil à dba.stackexchange.com/questions/202211/… . J'aimerais vraiment savoir comment Froid va performer dans le cas décrit
Roman Pekar
@Roman J'ai commenté votre question.
Karthik
1
Merci, @Karthik, pour le travail que vous avez fait sur le papier Froid, et dans vos efforts (et ceux des groupes) pour améliorer la convivialité des
FDU