web-dev-qa-db-fra.com

Le compte SQL Server 2014 (distinct X) ignore le vecteur de densité de statistiques pour la colonne x

Pour une COUNT(DISTINCT) ~ 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, c'est donc un bogue dans SQL Server 2014 que je devrais 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

enter image description here

Script complet

Voici une reproduction complète de la situation à l'aide d'une base de données STATS uniquement .

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

J'ai creusé dans les statistiques de la colonne pertinente et j'ai 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. SQL Server 2014, surprenant, semble ignorer l'estimation très précise fournie par les statistiques et utilise plutôt une estimation beaucoup plus faible. Cela produit un plan beaucoup plus lent qui ne réserve pas assez de mémoire et de déversements à TEMPDB.

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

Connecter le problème

Sur la base des réponses à cette question, j'ai également déposé cela comme un problème de connexion

16
Geoff Patterson

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

Stats derivation

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

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

PK Stats

Cela indique 2 980 235 lignes échantillonnées de 3 439 431 721 avec un vecteur de densité au niveau COL5 de 3,35544e-07. La réciproque de celle qui donne un certain nombre de valeurs distinctes de 2 980 235 arrondies à l'aide de 2 980 240.

Maintenant, la question est, étant donné que les statistiques échantillonnées, quelles hypothèses le modèle doit faire sur le nombre de valeurs distinctes. Je m'attendrais à ce qu'elle extrapolait, mais cela n'est pas fait et peut-être délibérément.

Plus intuitivement, j'attendrais qu'au lieu d'utiliser les statistiques multi-colonnes, il examinerait la densité sur Col5 (mais cela ne le fait pas):

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

Col5 stats

Ici, la densité est 9.266754E-10, dont la réciproque est 1 079 126.528 .

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

L'élément de connexion que vous avez ouvert, SQL 2014 STAND 2014 STATISTINCLE STATISTINCLES STATISTIQUES RÉLÉDURE LES STATISTIQUES PRESSIQUES SIMNE-COLUMNIQUES POUR LES COLONMES NON-LEUR , est marquée fixe Pour SQL Server 2017.

15
Paul White 9