J'ai remarqué cela tout en faisant des tests de performance récemment. Lorsque j'insère une valeur dans une colonne qui nécessitera une conversion implicite (E.G. bigint
dans nvarchar
), je reçois un avertissement:
Tapez la conversion dans l'expression
(CONVERT_IMPLICIT(nvarchar(50),[tempdb].[dbo].[#MyFunIntTable].[EvenCoolerColumn],0))
peut affecter la "estimation de la cardinalité" dans le choix du plan de requête.
En tant que citoyen concerné, j'ai vérifié tous les suspects évidents et éventuellement creusé dans le XML pour confirmer qu'il s'agissait d'un avertissement de l'insertion dans la table. Le problème est que je ne peux pas comprendre pourquoi cela affecterait jamais les estimations de la cardinalité. Si je faisais cela dans une jointure ou quelque part avec un peu plus de logique, cela aurait un sens, mais il ne devrait pas y avoir une incompatibilité d'estimation de la cardinalité pour l'opération d'insertion réelle, non?
J'ai remarqué que cela s'est passé lorsqu'il s'agissait d'une seule requête triviale - dès que plus d'une valeur est insérée, ou nous tirons une valeur d'une table, nous avons frappé cela.
Cette question a attiré certains doublons potentiels, notamment:
Je pense que c'est différent de ces questions parce que je ne fais rien littéralement avec cette colonne. Je ne l'utilise pas dans un filtre, ou une sorte, ou un groupe, ou une jointure, ou dans une fonction - l'une de ces choses rend le scénario plus compliqué. Tout ce que je fais, c'est insérer un bigint
dans un nvarchar
, qui ne devrait jamais avoir une incidence sur une estimation de cardinalité significative que je peux penser.
Ce que je cherche spécifiquement d'une réponse est:
Je l'ai recréé avec l'exemple ci-dessous ( Coller le plan )
DROP TABLE IF EXISTS #MyFunStringTable;
DROP TABLE IF EXISTS #MyFunIntTable;
CREATE TABLE #MyFunStringTable
(
SuperCoolColumn nvarchar(50) COLLATE DATABASE_DEFAULT NULL
);
CREATE TABLE #MyFunIntTable
(
EvenCoolerColumn bigint NULL
);
INSERT INTO #MyFunIntTable
( EvenCoolerColumn )
VALUES
( 1 ),
( 2 ),
( 3 ),
( 4 ),
( 5 );
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
SELECT EvenCoolerColumn
FROM #MyFunIntTable;
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
VALUES
( 1 );
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
VALUES
( 1 ),
( 2 );
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
SELECT 1;
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
SELECT 1
UNION ALL
SELECT 2;
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
SELECT 1
FROM #MyFunIntTable;
Comme d'autres avertissements de plan d'exécution, celui-ci est informatif. Si votre requête a effectué lentement, ou si vous avez remarqué que les estimations de cardinalité étaient incorrectes, l'avertissement vous donnerait des informations sur la recherche d'une cause possible.
En tant que matière purement pratique, c'est à peu près la fin de celui-ci. Les conditions précises qui déclenchent cet avertissement d'optimiseur sont sans papiers.
Cela dit, je vais entrer dans un peu de détails pour satisfaire un peu votre curiosité.
1. Une explication de la raison pour laquelle je reçois cet avertissement malgré tout d'intérêts en cours - est-ce que SQL Server sera conservateur et signalera même quand cela n'affectera pas le choix du plan?
Là sont les choses qui présentent intéressent le composant d'estimation de la cardinalité de l'optimiseur de requête. Ce composant tient une trace d'une large gamme de propriétés et d'autres informations pour chaque opérateur logique de l'arborescence de la requête. Cela inclut des histogrammes (à partir du disque ou dérivé entièrement en mémoire), des informations de domaine, des dépendances fonctionnelles, etc.
Dans votre exemple spécifique, l'avertissement est déclenché lorsque l'entrée à la convertie est connue pour être monotone mais la sortie n'est pas. Conversion de integer
littéral à bigint
conserve cette propriété. Conversion de bigint
à nvarchar(50)
ne le fait pas.
Lorsqu'il y a une seule constante d'entier littéral, le pliage de la constante d'analyse de temps convertit sur nvarchar
avant l'optimisation commence. Cela évite la conversion de type dans le plan et l'avertissement associé.
Il existe des différences de mise en œuvre internes détaillées entre l'estimateur de cardinalité d'origine et le nouvel estimateur de cardinalité qui signifiera certaines déclarations générera un avertissement sous une seule CE mais pas l'autre.
2. Quelle estimation de cardinalité est en réalité en danger ici et quelle opération changerait basée sur des inexactitudes dans cette estimation de la cardinalité?
Dans vos énoncés d'exemple, aucun. Comme indiqué, la conversion peut affecter d'autres données internes, ce qui pourrait affecter par ex. autres opérateurs de plan, ou le chemin du code pris via l'optimiseur. Le point large est qu'il y a plus qu'une estimation de la cardinalité brute à considérer. Les différences internes peuvent affecter des éléments tels que la vue indexée ou la correspondance de colonne calculée, entre autres possibilités.
3. Existe-t-il un scénario où cela pourrait affecter le choix du plan? Évidemment, si je commence à rejoindre ou à filtrer sur la colonne convertie, cela pourrait, mais comme?
Cela semble être identique à la question précédente.
4. Y a-t-il quelque chose qui peut être fait pour l'empêcher d'alerter, outre la modification des types de données (supposer qu'il s'agit de la manière dont les modèles de données interagissent)
Il n'y a aucune option pour désactiver ces avertissements.