Por que meus índices não clusterizados usam mais espaço ao excluir linhas?

22

Eu tenho uma tabela grande com 7,5 bilhões de linhas e 5 índices. Quando excluo aproximadamente 10 milhões de linhas, percebo que os índices não clusterizados parecem aumentar o número de páginas em que estão armazenados.

Eu escrevi uma consulta contra dm_db_partition_statspara relatar a diferença (depois - antes) nas páginas:

delm dm_db_partition_stats

O índice 1 é o índice clusterizado, o índice 2 é a chave primária. Os outros são não clusterizados e não exclusivos.

Por que as páginas estão aumentando nesses índices não agrupados?
Eu esperava que os números continuassem os mesmos.
Eu vejo os contadores de desempenho relatando um aumento nas divisões de páginas durante a exclusão.

Ao excluir, o registro fantasma precisa passar para outra página? Isso tem a ver com "exclusivos"?

Estamos no meio do lançamento do RCSI, mas, no momento, o RCSI está desativado.

É um nó primário em um grupo de disponibilidade. Eu sei que o instantâneo é usado de alguma forma em secundários. Eu ficaria surpreso se isso fosse relevante. Eu pretendo me aprofundar nisso (procurando a saída da página dbcc) para saber mais. Esperamos que alguém tenha visto algo semelhante.

Michael J Swart
fonte
Apenas uma pergunta - executando uma REORGANIZAR em um dos índices que cresceram, o que acontece? Quantas páginas são removidas? E se você reorganizar antes de excluir, o que acontece? Estou pensando principalmente que os mecanismos internos podem achar mais fácil, em alguns casos, alocar uma nova página inteira e mesclar, mas não limpa as páginas vazias. Sei que REORGANIZE acaba descartando quantidades significativas de páginas, mesmo em índices relativamente não-fragmentados, mas maiores.
Rindo Vergil
Boa pergunta @LaughingVergil Quando tiver a resposta, voltarei aqui para denunciá-la. (Mas pode demorar um pouco).
Michael J Swart
No nosso caso, esse aumento foi um fenômeno temporário. Com paciência suficiente, a limpeza de fantasmas acabou fazendo seu trabalho e os tamanhos dos índices diminuíram.
Michael J Swart

Respostas:

28

Um cenário possível que me diverte muito:

  • As linhas foram gravadas originalmente quando o banco de dados não tinha RCSI (Read Committed Snapshot), Isolamento de Instantâneo (SI) ou Grupos de Disponibilidade (AGs) ativados
  • RCSI ou SI foi ativado ou o banco de dados foi adicionado a um Grupo de Disponibilidade
  • Durante as exclusões, um carimbo de data e hora de 14 bytes foi adicionado às linhas excluídas para dar suporte às leituras RCSI / SI / AG

Como esse servidor é primário em um AG, ele é afetado da mesma forma que os secundários. As informações da versão são adicionadas no primário - as páginas de dados são exatamente as mesmas, tanto nas primárias quanto nas secundárias. Os secundários utilizam o armazenamento de versão para fazer suas leituras enquanto as linhas estão sendo atualizadas pelo AG, mas os secundários não gravam suas próprias versões do carimbo de data / hora na página. Eles apenas herdam as versões do trabalho do primário.

Para demonstrar o crescimento, peguei a exportação do banco de dados Stack Overflow (que não possui o RCSI ativado) e criei vários índices na tabela Postagens. Verifiquei os tamanhos dos índices com sp_BlitzIndex @Mode = 2 (copiei / colei em uma planilha e limpei um pouco para maximizar a densidade de informações):

sp_BlitzIndex antes

Eu apaguei cerca de metade das linhas:

BEGIN TRAN;
DELETE dbo.Posts WHERE Id % 2 = 0;
GO

Divertidamente, enquanto as exclusões estavam acontecendo, o arquivo de dados estava crescendo para acomodar os carimbos de data e hora também! O Relatório de uso de disco do SSMS mostra os eventos de crescimento - aqui está apenas o topo para ilustrar:

Eventos de crescimento

(Preciso amar uma demonstração em que as exclusões aumentem o banco de dados.) Enquanto a exclusão estava em execução, executei o sp_BlitzIndex novamente. Observe que o índice clusterizado tem menos linhas, mas seu tamanho já aumentou cerca de 1,5 GB. Os índices não clusterizados no AcceptedAnswerId cresceram dramaticamente - são índices com um valor pequeno que é quase nulo; portanto, seus tamanhos de índice quase dobraram!

sp_BlitzIndex durante a exclusão

Não preciso esperar a exclusão terminar para provar isso, então pararei a demo por lá. Aponte o seguinte: quando você faz grandes exclusões em uma tabela que foi implementada antes da ativação do RCSI, SI ou AGs, os índices (incluindo o clusterizado) podem aumentar para acomodar a adição do carimbo de data / hora do armazenamento de versão.

Brent Ozar
fonte
3
Esta é a explicação. Acontece que existem outras circunstâncias que podem levar à falta de 14 bytes da versão. Nos meus testes, parece que a reconstrução de um índice offline reconstruirá as linhas sem os bytes da versão.
Michael J Swart