SQL Server 2014 COUNT (DISTINCT x) ignore le vecteur de densité de statistiques pour la colonne x


15

Pour un COUNT(DISTINCT)qui a ~ 1 milliard de valeurs distinctes, je reçois un plan de requête avec un agrégat de hachage estimé à seulement ~ 3 millions de lignes.

Pourquoi cela arrive-t-il? SQL Server 2012 produit une bonne estimation, est-ce donc un bogue dans SQL Server 2014 que je dois signaler sur Connect?

La requête et la mauvaise estimation

-- Actual rows: 1,011,719,166
-- SQL 2012 estimated rows: 1,079,130,000 (106% of actual)
-- SQL 2014 estimated rows: 2,980,240 (0.29% of actual)
SELECT COUNT(DISTINCT factCol5)
FROM BigFactTable
OPTION (RECOMPILE, QUERYTRACEON 9481) -- Include this line to use SQL 2012 CE

-- Stats for the factCol5 column show that there are ~1 billion distinct values
-- This is a good estimate, and it appears to be what the SQL 2012 CE uses
DBCC SHOW_STATISTICS (BigFactTable, _WA_Sys_00000005_24927208)
--All density   Average Length  Columns
--9.266754E-10  8               factCol5
SELECT 1 / 9.266754E-10
-- 1079126520.46229

Le plan de requête

entrez la description de l'image ici

Script complet

Voici une reproduction complète de la situation en utilisant une base de données uniquement statistiques .

Ce que j'ai essayé jusqu'à présent

J'ai fouillé dans les statistiques de la colonne pertinente et constaté que le vecteur de densité montre environ 1,1 milliard de valeurs distinctes. SQL Server 2012 utilise cette estimation et produit un bon plan. Étonnamment, SQL Server 2014 semble ignorer l'estimation très précise fournie par les statistiques et utilise à la place une estimation beaucoup plus faible. Cela produit un plan beaucoup plus lent qui ne réserve pas assez de mémoire et se répand à tempdb.

J'ai essayé le drapeau de trace 4199, mais cela n'a pas réglé la situation. Enfin, j'ai essayé de creuser pour optimiser les informations via une combinaison d'indicateurs de trace (3604, 8606, 8607, 8608, 8612), comme démontré dans la seconde moitié de cet article . Cependant, je n'ai pu voir aucune information expliquant la mauvaise estimation jusqu'à ce qu'elle apparaisse dans l'arborescence de sortie finale.

Problème de connexion

Sur la base des réponses à cette question, j'ai également classé ce problème dans Connect

Réponses:


14

La façon dont l'estimation de la cardinalité est dérivée me semble certainement contre-intuitive. Le calcul de comptage distinct (visible avec les événements étendus ou les indicateurs de trace 2363 et 3604) est:

Dérivation des statistiques

Remarquez la casquette. La logique générale de cela semble très raisonnable (il ne peut pas y avoir de valeurs plus distinctes), mais le plafond est appliqué à partir des statistiques multi-colonnes échantillonnées :

DBCC SHOW_STATISTICS 
    (BigFactTable, [PK_BigFactTable])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

Statistiques PK

Cela montre 2980235 lignes échantillonnées sur 3439431721 avec un vecteur de densité au niveau Col5 de 3,35544E-07. L'inverse de cela donne un nombre de valeurs distinctes de 2 980 235 arrondies en utilisant les mathématiques réelles à 2 980 240.

Maintenant, la question est, compte tenu des statistiques échantillonnées, quelles hypothèses le modèle devrait faire sur le nombre de valeurs distinctes. Je m'attendrais à ce qu'il extrapole, mais cela ne se fait pas, et peut-être délibérément.

Plus intuitivement, je m'attendrais à ce qu'au lieu d'utiliser les statistiques multi-colonnes, il se penche sur la densité sur Col5 (mais ce n'est pas le cas):

DBCC SHOW_STATISTICS 
    (BigFactTable, [_WA_Sys_00000005_24927208])
WITH
    STAT_HEADER, 
    DENSITY_VECTOR;

Statistiques Col5

Ici, la densité est 9.266754E-10, dont l'inverse est 1.079.126.528 .

Une solution de contournement évidente entre-temps consiste à mettre à jour les statistiques multi-colonnes avec une analyse complète. L'autre consiste à utiliser l'estimateur de cardinalité d'origine.

L'élément Connect que vous avez ouvert, les statistiques multi-colonnes échantillonnées SQL 2014 remplacent les statistiques mono-colonne plus précises pour les colonnes non principales , est marqué Fixe pour SQL Server 2017.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.