DBCC PAGE

Continuando a série dos comandos históricos, vamos falar sobre o famoso DBCC PAGE. Esse é o quarto artigo da série: já comentei sobre o SET STATISTICS IO, DBCC DROPCLEANBUFFERS e DBCC SHOWCONTIG.

Vou recriar o ambiente do LOJADB:

image

Em seguida, quero me certificar que está funcionando tudo corretamente.

image

Antes de continuar, algumas pessoas desconfiaram da forma como construi a tabela. Estou usando o tipo de dados CHAR(800) ao invés do tradicional VARCHAR. Por isso, vou mudar o tipo de coluna. Por ser um tipo variável, vou trocar para VARCHAR(1000).

image

A tabela foi alterada para a nova coluna VARCHAR.

image

Rodei o sp_spaceused antes de começar os testes para validar a quantidade de registro e o tamanho da tabela. Curiosamente, não lembro da tabela ocupar 20MB, parece que está maior.

image

Vamos fazer o teste de desempenho. Começarei limpando o cache e depois habilitando o SET STATISTICS TIME e SET STATISTICS IO.

image

Apenas para manter a consistência dos testes, vou desabilitar o read-head usando o Trace Flag global 652. Limpando o cache e executando novamente:

image

Consegui bater o recorde do tempo! Agora a query está rodando em 2659ms.

 

Investigação usando o DBCC PAGE

Por algum motivo houve um aumento significativo no número de logical reads (7502), assim como nas leituras físicas (2506). Por isso, comecei olhando as páginas em memória do Buffer Pool. Encontrei exatamente 2509 páginas pertencentes ao LOJADB. No entanto, o que me chamou a atenção foi existir páginas com 8 registros e outras, com apenas 4.

image

A investigação continua com a ajuda do DBCC PAGE.

Esse comando está disponível desde os primórdios do SQL Server e deve ser usado em conjunto com o Trace Flag 3604.

DBCC PAGE (SQL 6.5)
https://support.microsoft.com/en-us/kb/83065

A sintaxe é simples:

DBCC PAGE(dbid, file_id, page_id, opt)

Vamos investigar a página 26057, que possui 4 registros.

image

Cabeçalho:

image

image

A resposta está no tipo de registro armazenado! Esses 4 registros são FORWARDED_RECORD.

Rodando o DBCC PAGE nas páginas com 8 registros, encontro os ponteiros FORWARDING_STUB:

image

O mistério está resolvido. Ao executar o comando ALTER TABLE - ALTER COLUMN, os registros foram “expulsos” da página para uma página externa usando os mecanismos de “forwarded records”.

Existe uma boa explicação disso no livro “Inside SQL Server”. Também encontrei esse artigo do Paul Randal:

Inside the Storage Engine: Anatomy of a record
https://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-a-record/

 

Conclusão

Ao mudar o tipo de dado da coluna, forçamos a ocorrência de Forwarded Records e causamos a fragmentação de dados em disco. Esse problema ocorreu porque a tabela está organizado como Heap e não estamos trabalhando com Clustered Index.

No próximo artigo, vou mostrar um comportamento muito curioso das Heaps. Ainda preciso pensar no título.