Beaucoup a été écrit sur les périls des FDU scalaires dans SQL Server. Une recherche occasionnelle renverra des tas de résultats.
Il existe cependant des endroits où une UDF scalaire est la seule option.
À titre d'exemple: lorsqu'il s'agit de XML: XQuery ne peut pas être utilisé comme définition de colonne calculée. Une option documentée par Microsoft consiste à utiliser un Scalar UDF pour encapsuler votre XQuery dans un Scalar UDF, puis à l'utiliser dans une colonne calculée.
Cela a divers effets et certaines solutions de contournement.
Vous pouvez contourner l'exécution ligne par ligne en liant schématiquement la fonction et en persistant la colonne calculée ou en l'indexant. Aucune de ces méthodes ne peut empêcher la sérialisation forcée des requêtes atteignant la table, même lorsque l'UDF scalaire n'est pas référencé.
Existe-t-il un moyen connu de le faire?
Oui si vous:
PERSISTED
Plus précisément, au moins les versions suivantes sont requises :
[~ # ~] mais [~ # ~] pour éviter un bug (ref pour 2014 , et pour 2016 et 2017 ) introduit dans ces correctifs, appliquez plutôt:
L'indicateur de trace est efficace en tant qu'option de démarrage –T
, À la fois sur l'étendue globale et sur la session en utilisant DBCC TRACEON
, Et par requête avec OPTION (QUERYTRACEON)
ou un guide de plan.
L'indicateur de trace 176 empêche l'expansion persistante de la colonne calculée.
La charge de métadonnées initiale effectuée lors de la compilation d'une requête apporte toutes les colonnes, pas seulement celles directement référencées. Cela rend toutes les définitions de colonnes calculées disponibles pour la correspondance, ce qui est généralement une bonne chose.
Comme effet secondaire malheureux, si l'une des colonnes chargées (calculées) utilise une fonction scalaire définie par l'utilisateur, sa présence désactive le parallélisme pour la requête entière , même lorsque la colonne calculée n'est pas réellement utilisée .
L'indicateur de trace 176 aide à cela, si la colonne est persistante, en ne chargeant pas la définition (car l'expansion est ignorée). De cette façon, une fonction scalaire définie par l'utilisateur n'est jamais présente dans l'arbre de requête de compilation, donc le parallélisme n'est pas désactivé.
Le principal inconvénient de l'indicateur de trace 176 (en plus d'être seulement légèrement documenté) est qu'il empêche également la correspondance d'expression de requête avec des colonnes calculées persistantes: si la requête contient une expression correspondant à une colonne calculée persistante, l'indicateur de trace 176 empêchera l'expression d'être remplacée par une référence à la colonne calculée.
Pour plus de détails, consultez mon article SQLPerformance.com, Colonnes calculées correctement persistantes .
Étant donné que la question mentionne XML, comme alternative à la promotion de valeurs à l'aide d'une colonne calculée et d'une fonction scalaire, vous pouvez également envisager d'utiliser un index XML sélectif, comme vous l'avez écrit dans Index XML sélectifs: pas mal du tout =.
En plus de l'excellent @ Paul's Oui # 1 , il y a en fait un Oui # 2 qui:
PERSISTED
, etLes seuls inconvénients (pour autant que je sache) sont:
Et cette option est: [~ # ~] sqlclr [~ # ~]
C'est vrai. Un aspect intéressant des FDU scalaires SQLCLR est que, si ils ne font aucun accès aux données (ni utilisateur ni système), alors ils n'interdisent pas le parallélisme. Et ce n'est pas seulement de la théorie ou du marketing. Bien que je n'aie pas le temps (pour le moment) de rédiger un compte rendu détaillé, j'ai testé et prouvé cela.
J'ai utilisé la configuration initiale du billet de blog suivant (j'espère que l'O.P.ne considère pas que ce soit une source peu fiable ????):
Jeans Bad Idea: plusieurs indices
Et effectué les tests suivants:
([c2] * [c3])
─⇾ Parallélisme (comme prévu)SCHEMABINDING
) définie comme RETURN (@First * @Second);
─⇾ AUCUN parallélisme (comme prévu)IsDeterministic = true
Et = false
) Définie comme return SqlInt32.Multiply(First, Second);
─ ⇾ Parallélisme (woo hoo !!) Ainsi, bien que SQLCLR ne fonctionne pas pour tout le monde, il a certainement ses avantages pour les personnes/situations/environnements qui conviennent bien. Et, en ce qui concerne cette question spécifique - l'exemple donné en ce qui concerne l'utilisation de XQuery - cela fonctionnerait certainement pour cela (et, selon ce qui est spécifiquement fait, cela pourrait même être un peu plus rapide ????).