COUNT do SQL Server 2014 (DISTINCT x) ignora o vetor de densidade de estatísticas da coluna x

15

Para um COUNT(DISTINCT)que tenha ~ 1 bilhão de valores distintos, estou recebendo um plano de consulta com um hash agregado estimado em apenas ~ 3 milhões de linhas.

Por que isso está acontecendo? O SQL Server 2012 produz uma boa estimativa; isso é um bug no SQL Server 2014 que devo reportar no Connect?

A consulta e estimativa ruim

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

O plano de consulta

insira a descrição da imagem aqui

Script completo

Aqui está uma reprodução completa da situação usando um banco de dados apenas de estatísticas .

O que eu tentei até agora

Analisei as estatísticas da coluna relevante e descobri que o vetor de densidade mostra estimados ~ 1,1 bilhões de valores distintos. O SQL Server 2012 usa essa estimativa e produz um bom plano. Surpreendentemente, o SQL Server 2014 parece ignorar a estimativa muito precisa fornecida pelas estatísticas e, em vez disso, usa uma estimativa muito menor. Isso produz um plano muito mais lento que não reserva memória suficiente e derrama o tempdb.

Tentei rastrear sinalizador 4199, mas isso não resolveu a situação. Por fim, tentei acessar as informações do otimizador por meio de uma combinação de sinalizadores de rastreamento (3604, 8606, 8607, 8608, 8612), conforme demonstrado na segunda metade deste artigo . No entanto, não pude ver nenhuma informação explicando a estimativa ruim até que ela apareceu na árvore de saída final.

Problema de conexão

Com base nas respostas a esta pergunta, também registrei isso como um problema no Connect

Geoff Patterson
fonte

Respostas:

14

A maneira como a estimativa da cardinalidade é derivada certamente parece contra-intuitiva para mim. O cálculo da contagem distinta (visível com Eventos estendidos ou sinalizadores de rastreamento 2363 e 3604) é:

Derivação de estatísticas

Observe a tampa. A lógica geral disso parece muito razoável (não pode haver valores mais distintos), mas o limite é aplicado a partir de estatísticas de várias colunas amostradas :

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

Estatísticas PK

Isso mostra 2.980.235 linhas amostradas de 3.439.431.721 com um vetor de densidade no nível Col5 de 3.35544E-07. O inverso disso fornece vários valores distintos de 2.980.235 arredondados usando matemática real para 2.980.240.

Agora, a questão é, dadas as estatísticas amostradas, que suposições o modelo deve fazer sobre o número de valores distintos. Eu esperaria que extrapolasse, mas isso não foi feito, e talvez deliberadamente.

Mais intuitivamente, eu esperaria que, em vez de usar as estatísticas de várias colunas, ele visse a densidade no Col5 (mas não):

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

Estatísticas Col5

Aqui a densidade é 9.266754E-10, a recíproca é 1.079.126.528 .

Uma solução óbvia nesse meio tempo é atualizar as estatísticas de várias colunas com varredura completa. A outra é usar o estimador de cardinalidade original.

O item do Connect que você abriu, as estatísticas de várias colunas amostradas do SQL 2014 substituem as estatísticas de coluna única mais precisas para colunas não principais , está marcado como Fixo no SQL Server 2017.

Paul White restabelece Monica
fonte