SQL Server 2014 COUNT (DISTINCT x) ignora il vettore di densità delle statistiche per la colonna x


15

Per un valore COUNT(DISTINCT)che ha ~ 1 miliardo di valori distinti, sto ottenendo un piano di query con un aggregato hash stimato di avere solo ~ 3 milioni di righe.

Perché sta succedendo? SQL Server 2012 produce una buona stima, quindi è un bug in SQL Server 2014 che dovrei segnalare su Connect?

La query e scarsa stima

-- 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

Il piano di query

inserisci qui la descrizione dell'immagine

Sceneggiatura completa

Ecco una riproduzione completa della situazione utilizzando un database di sole statistiche .

Quello che ho provato finora

Ho analizzato le statistiche per la colonna pertinente e ho scoperto che il vettore di densità mostra una stima di ~ 1,1 miliardi di valori distinti. SQL Server 2012 utilizza questa stima e produce un buon piano. SQL Server 2014, sorprendentemente, sembra ignorare la stima molto accurata fornita dalle statistiche e utilizza invece una stima molto più bassa. Questo produce un piano molto più lento che non riserva abbastanza memoria e si riversa su tempdb.

Ho provato a tracciare la bandiera 4199, ma ciò non ha risolto la situazione. Infine, ho provato a cercare informazioni sull'ottimizzatore tramite una combinazione di flag di traccia (3604, 8606, 8607, 8608, 8612), come dimostrato nella seconda metà di questo articolo . Tuttavia, non sono stato in grado di visualizzare alcuna informazione che spiegasse la stima errata fino a quando non è stata visualizzata nella struttura di output finale.

Problema di connessione

Sulla base delle risposte a questa domanda, ho anche presentato questo problema come un problema in Connect

Risposte:


14

Il modo in cui viene derivata la stima della cardinalità mi sembra certamente intuitivo. Il calcolo del conteggio distinto (visualizzabile con Eventi estesi o flag di traccia 2363 e 3604) è:

Derivazione delle statistiche

Notare il cappuccio. La logica generale di questo sembra molto ragionevole (non possono esserci valori più distinti), ma il limite viene applicato dalle statistiche multi-colonna campionate :

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

Statistiche PK

Ciò mostra 2.980.235 righe campionate su 3.439.431.721 con un vettore di densità al livello Col5 di 3.35544E-07. Il reciproco di ciò fornisce un numero di valori distinti di 2.980.235 arrotondati usando la matematica reale a 2.980.240.

Ora la domanda è, date le statistiche campionate, quali ipotesi il modello dovrebbe fare riguardo al numero di valori distinti. Mi aspetterei che estrapolasse, ma ciò non è fatto, e forse deliberatamente.

Più intuitivamente, mi aspetto che invece di utilizzare le statistiche multi-colonna, guarderebbe la densità su Col5 (ma non lo fa):

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

Statistiche Col5

Qui la densità è 9.266754E-10, il cui reciproco è 1.079.126.528 .

Una soluzione ovvia nel frattempo è aggiornare le statistiche multi-colonna con la scansione completa. L'altro è usare lo stimatore di cardinalità originale.

L'elemento Connect che hai aperto, le statistiche a più colonne campionate di SQL 2014 hanno la precedenza su statistiche a colonna singola più accurate per le colonne non iniziali , è contrassegnato come fisso per SQL Server 2017.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.