Installer
J'ai du mal à comprendre une estimation de cardinalité. Voici ma configuration de test:
- la version 2010 de la base de données Stack Overflow
- SQL Server 2017 CU15 + GDR (KB4505225) - 14.0.3192.2
- le nouveau CE (niveau de compatibilité 140)
J'ai ce proc:
USE StackOverflow2010;
GO
CREATE OR ALTER PROCEDURE #sp_PostsByCommentCount
@CommentCount int
AS
BEGIN
SELECT *
FROM dbo.Posts p
WHERE
p.CommentCount = @CommentCount
OPTION (RECOMPILE);
END;
GO
Il n'y a pas d'index ou de statistiques non cluster sur la dbo.Posts
table (un index cluster est activé Id
).
Lorsque vous demandez un plan estimé pour cela, les "lignes estimées" qui en sortent dbo.Posts
sont de 1 934,99:
EXEC #sp_PostsByCommentCount @CommentCount = 51;
L'objet de statistiques suivant a été créé automatiquement lorsque j'ai demandé le plan estimé:
DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);
Les faits saillants sont les suivants:
- Les statistiques ont un taux d'échantillonnage assez faible de 1,81% (67 796/3 744 192)
- Seulement 31 étapes d'histogramme ont été utilisées
- La valeur «Toute densité» est
0.03030303
(33 valeurs distinctes ont été échantillonnées) - Le dernier
RANGE_HI_KEY
de l'histogramme est 50, avecEQ_ROWS
1
Question
Le dépassement de toute valeur supérieure à 50 (jusqu'à 2 147 483 647 inclus) entraîne l'estimation de la ligne 1 934,99. Quel calcul ou valeur est utilisé pour produire cette estimation? L'estimateur de cardinalité hérité produit une estimation d'une ligne, soit dit en passant.
Ce que j'ai essayé
Voici quelques théories que j'ai eues, des choses que j'ai essayées ou des informations supplémentaires que j'ai pu creuser en y réfléchissant.
Vecteur de densité
J'ai d'abord pensé que ce serait le vecteur de densité, le même que si j'avais utilisé OPTION (OPTIMIZE FOR UNKNOWN)
. Mais le vecteur de densité pour cet objet stats est 3,744,192 * 0,03030303 = 113,460, donc ce n'est pas ça.
Événements prolongés
J'ai essayé de lancer une session Extended Event qui a collecté l' query_optimizer_estimate_cardinality
événement (dont j'ai entendu parler dans le billet de blog de Paul White, Cardinality Estimation: Combining Density Statistics ), et j'ai obtenu ce genre d'informations intéressantes:
<CalculatorList>
<FilterCalculator CalculatorName="CSelCalcColumnInInterval" Selectivity="-1.000"
CalculatorFailed="true" TableName="[p]" ColumnName="CommentCount" />
<FilterCalculator CalculatorName="CSelCalcAscendingKeyFilter" Selectivity="0.001"
TableName="[p]" ColumnName="CommentCount" UseAverageFrequency="true"
StatId="4" />
</CalculatorList>
Il semble donc que la CSelCalcAscendingKeyFilter
calculatrice ait été utilisée (l'autre dit qu'elle a échoué, quoi que cela signifie). Cette colonne n'est pas une clé, ni unique, ni nécessairement ascendante, mais peu importe.
Faire une recherche sur Google de ce terme m'a conduit à quelques articles de blog:
- Joe Sack - Le calculateur CSelCalcAscendingKeyFilter ,
- Itzik Ben-Gan - Cherchez et vous scannerez la partie II: touches ascendantes
Ces messages indiquent que le nouveau CE fonde ces estimations hors de l'histogramme sur une combinaison du vecteur de densité et du compteur de modification de la statistique. Malheureusement, j'ai déjà exclu le vecteur de densité (je pense?!), Et le compteur de modifications est nul (de sys.dm_db_stats_properties
toute façon).
Trace Flags
Forrest m'a suggéré d'activer TF 2363 pour obtenir plus d'informations sur le processus d'estimation. Je pense que la chose la plus pertinente de cette sortie est la suivante:
Plan for computation:
CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)
Selectivity: 0.000516798
C'est une percée (merci, Forrest!): Ce 0.000516798
nombre (qui semble avoir été arrondi de manière inutile dans l' Selectivity="0.001"
attribut XE ci-dessus) multiplié par le nombre de lignes dans le tableau est l'estimation que je cherchais (1934,99).
Il me manque probablement quelque chose d'évident, mais je n'ai pas réussi à inverser la façon dont cette valeur de sélectivité est produite à l'intérieur de la CSelCalcAscendingKeyFilter
calculatrice.