Por que a estatística criada automaticamente nesta coluna está vazia?

8

Info

Minha pergunta está relacionada a uma tabela moderadamente grande (~ 40 GB de espaço de dados) que é um heap
(infelizmente, não tenho permissão para adicionar um índice de cluster à tabela pelos proprietários do aplicativo)

Uma estatística criada automaticamente em uma coluna Identidade ( ID) foi criada, mas está vazia.

  • As estatísticas de criação automática e as estatísticas de atualização automática estão ativadas
  • Ocorreram modificações na tabela
  • Existem outras estatísticas (criadas automaticamente) que estão sendo atualizadas
  • Há outra estatística na mesma coluna criada por um índice (duplicado)
  • Versão: 12.0.5546

A estatística duplicada está sendo atualizada: insira a descrição da imagem aqui

A questão real

Para meu entendimento, todas as estatísticas podem ser usadas e as modificações são rastreadas, mesmo se houver duas estatísticas exatamente nas mesmas colunas (duplicatas), então por que essa estatística permanece vazia?

Estatísticas

insira a descrição da imagem aqui

Informações sobre estatísticas do banco de dados

insira a descrição da imagem aqui

Tamanho da tabela

insira a descrição da imagem aqui

Informações da coluna em que a estatística é criada

insira a descrição da imagem aqui

[ID] [int] IDENTITY(1,1) NOT NULL

Coluna de identidade

select * from sys.stats  
where name like '%_WA_Sys_0000000A_6B7099F3%';

insira a descrição da imagem aqui Criado automaticamente

Obtendo algumas informações sobre outra estatística

select * From sys.dm_db_stats_properties (1802541555, 3)  

insira a descrição da imagem aqui

Em comparação com o meu stat vazio:

insira a descrição da imagem aqui

Estatísticas + Histograma de "gerar scripts":

/****** Object:  Statistic [_WA_Sys_0000000A_6B7099F3]    Script Date: 2/1/2019 10:18:19 AM ******/

    CREATE STATISTICS [_WA_Sys_0000000A_6B7099F3] ON [dbo].[table]([ID]) WITH STATS_STREAM = 0x01000000010000000000000000000000EC03686B0000000040000000000000000000000000000000380348063800000004000A00000000000000000000000000

Ao criar uma cópia das estatísticas, nenhum dado está dentro

CREATE STATISTICS [_WA_Sys_0000000A_6B7099F3_TEST] ON [dbo].[table]([ID]) WITH STATS_STREAM = 0x01000000010000000000000000000000EC03686B0000000040000000000000000000000000000000380348063800000004000A00000000000000000000000000

insira a descrição da imagem aqui

Ao atualizar manualmente as estatísticas, elas são atualizadas.

UPDATE STATISTICS [dbo].[Table]([_WA_Sys_0000000A_6B7099F3_TEST])

insira a descrição da imagem aqui

Randi Vertongen
fonte

Respostas:

9

Consegui reproduzir isso, tanto com uma estatística vazia quanto com uma estatística preenchida. Organizei a criação de uma estatística automática em uma tabela vazia e o índice foi criado posteriormente:

IF OBJECT_ID(N'dbo.Heap', N'U') IS NOT NULL
BEGIN
    DROP TABLE dbo.Heap;
END;
GO
CREATE TABLE dbo.Heap 
(
    id integer NOT NULL IDENTITY,
    val integer NOT NULL,
);
GO
-- Add 1000 rows
INSERT dbo.Heap
    WITH (TABLOCKX)
    (val)
SELECT
    SV.number
FROM master.dbo.spt_values AS SV
WHERE
    SV.[type] = N'P'
    AND SV.number BETWEEN 1 AND 1000;
GO
SELECT COUNT_BIG(*) 
FROM dbo.Heap AS H
JOIN dbo.Heap AS H2
    ON H2.id = H.id
WHERE H.id > 0
AND H2.id > 0;
GO
-- Empty table
TRUNCATE TABLE dbo.Heap;
GO
-- Repeat exact same query (RT = 500 + 0.2 * 1000 = 700)
GO
SELECT COUNT_BIG(*) 
FROM dbo.Heap AS H
JOIN dbo.Heap AS H2
    ON H2.id = H.id
WHERE H.id > 0
AND H2.id > 0;
GO
-- Add 1000 rows
INSERT dbo.Heap
    WITH (TABLOCKX)
    (val)
SELECT
    SV.number
FROM master.dbo.spt_values AS SV
WHERE
    SV.[type] = N'P'
    AND SV.number BETWEEN 1 AND 1000;
GO
-- Add index
ALTER TABLE dbo.Heap ADD 
    CONSTRAINT [PK dbo.Heap id]
    PRIMARY KEY NONCLUSTERED (id);
GO
SELECT
    S.[name],
    S.auto_created,
    DDSP.stats_id,
    DDSP.last_updated,
    DDSP.[rows],
    DDSP.rows_sampled,
    DDSP.steps,
    DDSP.unfiltered_rows,
    DDSP.modification_counter
FROM sys.stats AS S
CROSS APPLY sys.dm_db_stats_properties(S.[object_id], S.stats_id) AS DDSP
WHERE 
    S.[object_id] = OBJECT_ID(N'dbo.Heap', N'U');

Resultado

Descobri que as modificações continuam sendo rastreadas com precisão em todas as duplicatas não vazias, mas apenas uma estatística é atualizada automaticamente (independentemente da configuração assíncrona).

As atualizações automáticas de estatísticas ocorrem apenas quando o otimizador de consulta precisa de uma estatística específica e descobre que está desatualizada (uma recompilação relacionada à otimização).

O otimizador escolhe entre estatísticas duplicadas, conforme mencionado no documento Planejar cache e recompilações no SQL Server 2012 :

Um problema não diretamente relacionado ao tópico deste documento é: dadas várias estatísticas no mesmo conjunto de colunas na mesma ordem, como o otimizador de consultas decide quais carregar durante a otimização de consultas? A resposta não é simples, mas o otimizador de consulta usa diretrizes como: Dê preferência a estatísticas recentes sobre estatísticas antigas; Dê preferência às estatísticas computadas usando a FULLSCANopção àquelas calculadas usando amostragem; e assim por diante.

O ponto é que o otimizador escolhe uma das estatísticas duplicadas disponíveis (a "melhor) e é atualizada automaticamente se for considerada obsoleta.

Acredito que essa seja uma mudança de comportamento em relação a versões mais antigas - ou pelo menos a documentação sugere que todas as estatísticas desatualizadas de um objeto seriam atualizadas como parte desse processo, mas não tenho idéia de quando isso foi alterado. Certamente foi depois de agosto de 2013 quando Matt Bowler postou o Duplicate Statistics , que contém um repo prático baseado no AdventureWorks. Agora, esse script resulta em apenas um dos objetos estatísticos sendo atualizado, enquanto os dois estavam no momento.

A explicação acima corresponde a todos os comportamentos que observei ao tentar reproduzir seu cenário, mas duvido que esteja explicitamente documentado em qualquer lugar. Parece uma otimização sensata, pois há pouco valor em manter as duplicatas totalmente atualizadas.

Provavelmente, tudo isso está em um nível de detalhe abaixo do que a Microsoft está disposta a oferecer. Isso também significa que pode mudar sem aviso prévio.

Paul White 9
fonte