Como diminuir a fragmentação HEAP no SQL Server?

10

Recentemente, descobri que uma tabela de heap tinha mais de 70% de fragmentação. Então eu decidi fazer um

ALTER TABLE dbo.myTable REBUILD

Engraçado, depois tive 20% de fragmentação. Não havia gravação nessa mesa desde então. Então eu decidi fazer a reconstrução mais uma vez.

Após a 2ª vez, a tabela produz 50% de fragmentação, ainda mais! Eu realmente não entendo como isso pode acontecer ...

tuxmania
fonte
O que você quer dizer com dizer fragmentação lógica. É a fragmentação em termos de uso de páginas de dados. Eu sei que não há ordem, mas os dados não ordenados não são fragmentados em si. Fragmentação, neste caso, significa uso eficiente de páginas de dados.
Tuxmania
2
Acho que devemos perguntar, qual é o tamanho da mesa? Em linhas e páginas.
Cody Konior

Respostas:

17

O que significa fragmentação em um heap

O valor de fragmentação no Heap que você obtém da coluna avg_fragmentation_in_percentconsultando o sys.dm_db_index_physical_statsDMV afirma que

Fragmentação lógica para índices ou fragmentação de extensão para heaps na unidade de alocação IN_ROW_DATA.

Além disso, o mesmo BOL diz que

Essa é a porcentagem de extensões fora de ordem nas páginas de folha de uma pilha. Uma extensão fora de ordem é aquela em que a extensão que contém a página atual de um heap não é fisicamente a próxima extensão após a extensão que contém a página anterior.

Portanto, você pode ver que não é o espaço livre presente nas páginas alocadas ao Heap, mas a sequência variável de páginas que cria a fragmentação.

Isso pode ser demonstrado por um pequeno teste. Vamos criar uma tabela de heap e inserir alguns registros nela e depois verificar a fragmentação.

create table dbo.HeapTest
(
Id INT not NULL Default (1),
Col1   char(5000) Not null Default ('Heaps Are Cool')
)

SET NOCOUNT ON

Insert into dbo.Heaptest default values
go 50

select index_type_desc,avg_fragmentation_in_percent,fragment_count,
avg_page_space_used_in_percent,record_count
from sys.dm_db_index_physical_stats(db_id(),object_id('dbo.HeapTest','U'),0,default,'detailed')

Portanto, a tabela Heap é criada com 50 registros. Abaixo está a aparência da fragmentação após a consulta DMV sys.dm_db_index_physical stats

insira a descrição da imagem aqui

Você pode ver que o avg_fragmentation_in_percentvalor da coluna é 33%. Agora vamos ver como as páginas são organizadas. Isso pode ser feito usando uma consulta não documentada%%lockres%% . A consulta seria

SELECT  %%lockres%%, * FROM dbo.HeapTest;

E abaixo está a aparência da saída. Anexando apenas uma parte relevante. A consulta produziu 50 linhas desde que inserimos 50 linhas em nossa tabela dbo.HeapTest.

insira a descrição da imagem aqui

O que diz é que a primeira página tem ID, 197a página seguinte tem ID. As 242páginas subseqüentes têm ID contínuo até chegarmos ao ID da página, 264porque depois obtemos o ID da página 280. Portanto, esse salto nos números de identificação da página é o que realmente está causando a fragmentação.

Agora, para não reconstruir o heap e executar o comando novamente para ver a fragmentação e como as páginas são organizadas. Temos fragmentação como

insira a descrição da imagem aqui

Você pode ver a fragmentação é agora 14%.

Vamos ver os números de página alocados

insira a descrição da imagem aqui

Temos apenas um salto para descanso, todas as páginas são alocadas em série. Como apenas uma fragmentação de salto diminuiu consideravelmente.

Reconstruo o Heap novamente e agora, quando verifiquei a fragmentação, ele havia desaparecido completamente. E a alocação de ID da página é como

insira a descrição da imagem aqui

Por que a fragmentação aumentou

Agora, com relação ao que poderia ter causado o aumento da fragmentação, podemos corroborar o fato de que, quando as páginas estavam sendo alocadas para o heap, elas não seriam contínuas, como você viu acima, o que causou o aumento do valor da fragmentação foi um salto nos IDs de PAGE alocados nas páginas.

Na parte de trás da cabeça, você também deve ter em mente que a palavra fragmentação para HEAP não tem nenhum significado, como você definiria a fragmentação para várias páginas não ordenadas.

Realmente preocupado com a fragmentação

Se você realmente enfrentar um cenário em que a tabela de heap está fragmentada e reduz a velocidade de consultas, seria melhor criar um índice de cluster na tabela do que reconstruí-lo. O motivo é quando você reconstrói a pilha todos os índices não clusterizados subjacentes também são reconstruídos, levando o processo de reconstrução a demorar muito mais tempo, utilizando muitos recursos e inchando o log de transações. Em um sistema de produção, sempre se tentava evitar isso. Paulo cobriu isso em sua seção Mito sobre a pilha .

PS: Por favor, não use comando não documentado no sistema de produção. Isso foi apenas para demonstração.

Shanky
fonte
Obrigado pela sua análise detalhada. Estou enfrentando grandes tabelas de heap porque alguns entusiastas do cofre de dados acham que é muito melhor do que usar índices agrupados, mas eles usam muitas restrições de verificação e índices não agrupados nesses heaps, então eu realmente não vejo o benefício dos heaps nessa situação. No entanto, como eu sou apenas o desenvolvedor estúpido, tenho que lidar com isso. Obrigado novamente para a visão :)
tuxmania
Como você executa selecionar index_type_desc, avg_fragmentation_in_percent, fragment_count, avg_page_space_used_in_percent, record_count a partir de sys.dm_db_index_physical_stats (db_id (), object_id ('dbo.HeapTest', 'U'), 0, apenas o resultado do retorno para o resultado padrão uma mesa ? ele retorna em todos os índices em todas as tabelas para mim mesmo que eu correcty especificar o meu nome de tabela em 'object_id'
Mickael
@Mickael Eu usei a função db_id () que usaria o banco de dados atual e especifiquei o nome do objeto para que ele sempre procure o banco de dados atual e procure Heapteste forneça o resultado. Tenho certeza que você pode ter perdido alguma coisa. Apenas certifique-se nível de compatibilidade não é 80 em que a função caso db_id doente não trabalho
shanky
@ Shank, por que você não recomenda usar a consulta não documentada %% lockres %% na produção? Você poderia explicar isso em detalhes?
22419 Ralph
@ user1624552 Simplesmente porque não está documentado, significa que a MS também não mantém a documentação atualizada. Quais são seus efeitos posteriores, como ele funciona não está documentado em nenhum lugar e é por isso que é solicitado. Ex existe o comando fn_dump_dblog () que cria um agendador oculto e isso não é bom. Este comando também não é suportado. Você pode usá-lo, mas o risco está em você.
shanky