Nous avons un générateur SQL qui émet des instructions conditionnelles SQL de manière générique pour les champs spécifiés (ce qui, pour les besoins de la discussion: nous appellerons myField
).
Si myField
est de type NVARCHAR
, nous pouvons faire une comparaison dudit champ à une chaîne comme ceci: myField = 'foo'
.
Cependant, cela ne fonctionne pas pour les champs de type NTEXT
. Ainsi, nous devons faire la comparaison avec un casting: CAST(myField as NVARCHAR(MAX)) = 'foo'
. Cela fonctionnera en fait si myField
est de type NVARCHAR
ou NTEXT
.
Quelle est la performance de faire le casting susmentionné sur un champ qui est déjà de type NVARCHAR
? Mon espoir est que SQL Server est assez intelligent pour reconnaître dynamiquement ce myField
type déjà NVARCHAR
(en transformant efficacement le CAST
no-op).
la source
Réponses:
Si le transtypage de la colonne a exactement le même type de données et la même longueur et que le prédicat de recherche est un littéral, il semble en effet ne pas en tenir compte ou le traiter comme un no-op et effectue une recherche d'index sur l'égalité.
Si le transtypage de la colonne est du même type de données mais de plus grande longueur et que le prédicat de recherche est un littéral de chaîne, il provoque un balayage d'index. Ceci est évidemment à éviter.
Si le transtypage de la colonne est du même type de données et de la même longueur ou plus et que le prédicat de recherche est une variable locale, il ajoute un opérateur scalaire de calcul au plan d'exécution. Cela appelle
GetRangeThroughConvert
et génère une plage.Cette plage est utilisée pour faire une recherche d'index et semble assez efficace
Code de test
la source
En général, la fonction
CAST
tue les performances car elle invalide toute utilisation des recherches d'index comme le montre le dernier exemple de Martin Smith. Lanvarchar(max)
conversion vers ou vers une longueur différente signifie un type de données différent: le fait que toutnvarchar
soit sans importance.En plus de cela, le type de données du côté droit de la comparaison importe également. S'il s'agit d'une variable locale ou d'un paramètre d'une longueur différente, un côté sera implicitement
CAST
au plus large des 2 types de données (voir la priorité des types de données ).En gros, si vous avez un général
CAST
ànvarchar(max)
elle bollix les choses. J'envisagerais de corriger l'utilisation dentext
avant d'ajouter un peuCAST
partout.La conversion peut ne pas s'afficher dans le plan de requête. Voir l'article du blog de Paul White
la source
Juste une note, Casting comme ceci où Datecreated est datetime
Ne rompt pas la capacité de SQL à utiliser des index si des index existent et s'ils n'existent pas, peut entraîner la journalisation d'un index manquant.
De même, lors de la conversion de
int
verstinyint
oubigint
versint
etc, la fonction de conversion n'empêche pas SQL d'utiliser des index SI l'optimiseur sait que l'opération de conversion ne change pas l'ordre de tri des 2 types de données comparables.Voici un tas de tests que vous pouvez exécuter et afficher le plan réel en utilisant Adventureworks2008R2
la source