Onde as estatísticas estão fisicamente armazenadas no SQL Server?

27

Onde as estatísticas usadas pelo Query Optimizer estão fisicamente armazenadas em um arquivo de banco de dados do SQL Server e no Buffer Pool?

Mais especificamente, existe uma maneira de descobrir as páginas usadas pelas estatísticas usando DMVs e / ou DBCC?

Eu possuo livros do SQL Server 2008 Internals e do SQL Server Internals and Troubleshooting e nenhum deles fala sobre a estrutura física das estatísticas; se eles não conseguirem encontrar essas informações.

ivanmp
fonte
11
Quando você cria uma cópia apenas estatística do banco de dados, ele mostra um binário em STATS_STREAMque eu nunca verifiquei se isso é algo que pode ser encontrado no próprio arquivo.
Martin Smith
2
As estatísticas são criadas por uma função agregada somente interna ( StatMan) que gera um blob (ironicamente, esse nome é destacado como uma função em uma janela de consulta do SSMS). Logicamente, as estatísticas estão associados com um índice ou um conjunto de colunas da tabela, por isso gostaria de começar por analisar as tabelas de metadados internos que procuram uma binaryou varbinarycoluna que vai levar para o blob. Isso deve ser visualizado usando DBCC PAGE, mas provavelmente não de outra maneira, porque é tudo interno.
22812 Jon Seigel
11
@ivanmp Editei sua pergunta para maior clareza, já que muitos dos DBAs mais novatos não saberão o que é BP ou QO.
Max Vernon
2
Costumava estar, sysindexes.statblobmas desde 2005, que retorna NULLe a localização é completamente sem documentos, apenas recuperável (que eu saiba) até DBCC SHOW_STATISTICS(o, i) WITH STATS_STREAM;.
Aaron Bertrand
11
Encontradas as estatísticas do índice - elas estão sys.sysidxstats-, parece que há um ponteiro LOB nessa tabela. Ainda não tenho certeza de onde estão as estatísticas da coluna; eles podem estar nessa tabela e também há uma typecoluna.
22812 Jon Seigel

Respostas:

30

Encontrei-os.

  1. Crie uma tabela com um objeto de estatísticas simples.

    CREATE DATABASE splunge;
    GO
    USE splunge;
    GO
    CREATE TABLE dbo.foo(bar INT, munge INT);
    GO
    CREATE STATISTICS x ON dbo.foo(bar);
    CREATE STATISTICS y ON dbo.foo(munge);
    GO
    INSERT dbo.foo SELECT s1.[object_id], s2.[object_id]
      FROM sys.objects AS s1
      CROSS JOIN sys.objects AS s2;
    GO
    UPDATE STATISTICS dbo.foo;
    GO
  2. Conecte-se usando o DAC (ADMIN:Server[\instance] ).

  3. Execute as seguintes consultas:

    DBCC SHOW_STATISTICS('dbo.foo', 'x') WITH STATS_STREAM;
    DBCC SHOW_STATISTICS('dbo.foo', 'y') WITH STATS_STREAM;
    
    SELECT name, imageval 
      FROM sys.stats AS s
      INNER JOIN sys.sysobjvalues AS o
      ON s.object_id = o.objid
      AND s.stats_id = o.subobjid
    WHERE 
      s.object_id = OBJECT_ID('dbo.foo');

Você notará que, imagevalpara cada objeto de estatísticas, não é o mesmo que o blob de estatísticas, mas contém o blob de estatísticas - é apenas um deslocamento. No meu sistema, isso resultou em x (obviamente truncei um bocado de bits):

0x0100...bunch of chars...000007000000C4E1BE00EEA0...rest the same
                            0x07000000C4E1BE00EEA0...rest the same

E isso para y:

0x0100...bunch of chars...430007000000C7E1BE00EEA0...rest the same
                            0x07000000C7E1BE00EEA0...rest the same

O mesmo aconteceu com as estatísticas baseadas em índices.

Provavelmente, você poderia validar ainda mais isso com uma série de consultas usando DBCCcomandos. Primeiro, descubra as páginas envolvidas no índice em cluster sys.sysobjvalues(substitua o nome do banco de dados):

DBCC IND('splunge', 'sys.sysobjvalues', 1);

O resultado listará várias páginas das quais você está interessado PageType = 1. Com um novo banco de dados, você poderá encontrar essas informações em uma das páginas com os PagePIDvalores mais altos. Por exemplo, no meu sistema, essa era a página 281, então eu olhei mais de perto nessa página:

DBCC TRACEON(3604);

DECLARE @dbid INT = DB_ID();

DBCC PAGE(@dbid, 1, 281, 3);

DBCC TRACEOFF(3604);

Com certeza, encontrei os dados no slot 17:

Resultados parciais da página DBCC

(Em bancos de dados maiores, talvez você precise fazer muito mais caça e bicar, já que não há garantia de que mesmo um novo objeto de estatística termine em uma nova página.

Vá em frente e tente fazer isso em casa, mas há um motivo para você se conectar ao DAC para isso. Eu ficaria curioso para saber, é claro, o que você fará com essas informações que você não poderá fazer com a DBCC SHOW_STATISTICSsaída.

Observe que isso obviamente não tenta decodificar o STATS_STREAMpara fornecer histograma ou outras informações, e não pude encontrar nenhuma evidência de que a saída tabular DBCC SHOW_STATISTICS ... WITH HISTOGRAMseja armazenada em qualquer lugar no formato de tabela. Joe Chang tem algumas informações sobre decodificação, se é isso que você procura. Eu não acho que é algo que você gostaria de fazer em uma consulta - basta usar DBCC.

Aaron Bertrand
fonte
2
Temos um vencedor, senhoras e senhores. Eu tiro meu chapéu para você, senhor.
Zane
Hahaha, parabéns e obrigado, senhor! Não se preocupe, não estou fazendo nada que não deva (também conhecido como "estúpido"). É apenas para crescimento pessoal. Fiquei realmente interessado nisso depois que percebi que não conseguia encontrar nada sobre isso em nenhum lugar. =)
ivanmp 18/10/12
Sobre o artigo de Joe Chang, eu o encontrei enquanto procurava a resposta para isso. Eu já tinha começado a ler. Obrigado novamente. :)
ivanmp 18/10/12