O ALTER INDEX ALL REBUILD usa mais espaço de log de transações com um modelo de recuperação simples do que reconstruir cada índice individualmente?

18

Uma operação "ALTER INDEX ALL REBUILD" no SQL Server 2012 falhou porque o log de transações ficou sem espaço. Os índices nunca foram reorganizados ou reconstruídos; portanto, a fragmentação é superior a 80% em quase todos eles.

O banco de dados usa um modelo de recuperação simples. Supus que, após cada operação de índice executada pelo formulário "ALL" do comando, os dados do log de transações fossem liberados antes da próxima reconstrução do índice. É assim que realmente funciona ou as recriações do índice são registradas como se fizessem parte de uma única transação?

Em outras palavras, eu poderia reduzir o crescimento do log de transações escrevendo um script para executar cada reconstrução individualmente? Existem outros fatores a serem considerados?

Falha no Google
fonte
2
Salvo dados explícitos, pelo contrário, eu assumiria que um comando SQL específico seria considerado uma única transação atômica pelo mecanismo DB. Nesse caso, você pode testar facilmente a teoria. Pegue seu maior índice e tente reconstruí-lo. Se isso der certo, é razoável supor que o log esteja acumulando informações de várias reconstruções. Se falhar, será necessário adicionar espaço para o log (pois há um problema de qualquer maneira) ou tentar reorganizar esse índice, em vez de reconstruir (se você não puder aumentar o espaço para o t- registro).
RDFozz
Sim, esse pensamento me ocorreu assim que terminei de digitar isso (efeito de pato de borracha), mas achei que seria melhor obter confirmação e deixar para outros que pensam da mesma maneira. Como não quero experimentar esse ambiente, provavelmente acabarei adicionando espaço aos logs de qualquer maneira.
Google Fail

Respostas:

16

Supus que, após cada operação de índice executada pelo formulário "ALL" do comando, os dados do log de transações fossem liberados antes da próxima reconstrução do índice. É assim que realmente funciona ou as recriações do índice são registradas como se fizessem parte de uma única transação?

1) Liberação de log: o modelo de recuperação SIMPLE não limpa o log após cada transação, mas nos pontos de verificação. ( link para mais informações)

2a) RECONSTRUIR TUDO: sim, RECONSTRUIR TUDO funciona como uma única transação. As recriações de índice dentro têm suas próprias transações, mas a operação geral não é totalmente confirmada até o final. Portanto, sim, você pode limitar o crescimento do arquivo de log reconstruindo índices individuais (e possivelmente emitindo comandos CHECKPOINT).

2b) Prova! Aqui, tenha um script de demonstração. (Desenvolvido no desenvolvimento de 2016) Primeiro, configure um banco de dados de teste, com tabela e índices:

USE master
GO

CREATE DATABASE Test_RebuildLog
GO

ALTER DATABASE Test_RebuildLog
SET RECOVERY SIMPLE
GO

USE Test_RebuildLog
GO

CREATE TABLE IndexTest
(ID int identity(1,1),
a char(1),
b char(1))

CREATE CLUSTERED INDEX CIX_IndexTest_ID ON IndexTest(ID)
CREATE INDEX IX_IndexTest_a ON IndexTest(a)
CREATE INDEX IX_IndexTest_b ON IndexTest(b)

INSERT IndexTest
(a,b)
VALUES ('a','b'),('z','y'),('s','r')

Agora você pode comparar a atividade de log entre REBUILD ALL e reconstruir individualmente

CHECKPOINT
GO
ALTER INDEX ALL ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

CHECKPOINT
GO
ALTER INDEX CIX_IndexTest_ID ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_a ON IndexTest REBUILD
ALTER INDEX IX_IndexTest_b ON IndexTest REBUILD

SELECT *
FROM sys.fn_dblog(NULL,NULL)
WHERE Operation = 'LOP_COMMIT_XACT'
OR Operation = 'LOP_BEGIN_XACT'
GO

Observe como a primeira transação aberta (ID de transação 0000: 000002fa para mim) não é confirmada até o final de REBUILD ALL, mas, para as recriações de índice por índice, elas são confirmadas sucessivamente.

Forrest
fonte
Uau, obrigado pela resposta realmente detalhada! Essa é uma ótima maneira de ver o que está acontecendo sob o capô, por assim dizer.
Google Fail
Bem explicado.
Ramakant Dadhichi
4

Tal como está, esta é uma transação única.

Pedro Lopes
fonte
6
Bem-vindo ao DBA.SE! Em geral, as melhores respostas não são simples afirmações, mas são apoiadas por informações de documentação ou artigos, ou (muitas vezes ainda melhor) por experiência pessoal que comprova a resposta indicada. Você pode expandir sua resposta para fornecer esse tipo de apoio?
RDFozz 10/07
2
Comentário da @RDFozz Fair, mas você viu o perfil de Pedro ? O acesso ao código-fonte provavelmente pode ser considerado mais autoritário do que a experiência ou documentação pessoal. :-)
Aaron Bertrand
3
@AaronBertrand - confesso, não o fiz. Eu certamente pensaria que fazer parte da equipe do SQL Server realmente se qualificaria. Ainda assim, vale a pena referenciar isso na resposta. +1, em qualquer caso.
RDFozz
3

A pergunta é trivial para uma reconstrução offline . Claro que é uma transação única. Imagine o caos que aconteceria se a operação dividisse cada índice em sua própria transação, pois teria que liberar os bloqueios ao confirmar e depois adquiri-los novamente. Enquanto a trava SCH-M da tabela crítica foi liberada, os índices podem ser eliminados e novos índices podem ser criados, como a instrução lidaria com esses casos? Sem mencionar que a tabela pode ser descartada e até recriada entre as duas transações! Incluindo o caso em que a tabela é descartada e uma tabela diferente é criada com o mesmo ID de objeto (sim, isso pode acontecer) ...

E se você aumentar a pergunta para dizer o que acontece se a reconstrução do índice for uma reconstrução online ? É uma transação única ou muitas? A resposta é complexa, pois na verdade existem várias transações internas envolvidas . No entanto, o ponto principal é que há uma transação de arquivamento geral que abrange toda a operação (a instrução ALTER) e isso fixa o log no local (não pode truncar), portanto, a operação precisa ser planejada de maneira a permitir dados ~ 1.6x tamanho para o modo de recuperação COMPLETO ou tamanho de dados 0,2x para o modo BULK_LOGGED / SIMPLE. Consulte o artigo vinculado para obter mais detalhes.

Você pode argumentar que por que o build offline não emprega as mesmas transações internas do modo online e divide a operação? Os problemas que eu mencionei sobre a tabela ser alterada / eliminada entre as operações de índice individuais (por exemplo, 'estabilidade do esquema' da tabela) ainda exigiriam que exista uma transação abrangente que mantenha um SCH-S na tabela durante toda a duração da instrução. Como essa transação também deve conter o SCH-S durante a recuperação, ela deve ser registrada e, como tal, haverá um registro de log BEGIN XACT que fixará o log e evitará o truncamento por toda a duração da instrução. Eu sei que esse problema específico estava sendo resolvido no período de tempo do SQL 2016-2017 (devido a problemas de tamanho de log do SQL Azure), mas não tenho certeza de que progresso foi feito . Parece que está em pré-visualização agora:A reconstrução do índice online recuperável está em visualização pública do SQL Server 2017 CTP 2.0 .

Remus Rusanu
fonte
0

Sim, eu tive esse mesmo problema com uma tabela muito grande. Sempre que eu emitia ALTER INDEX ALL, o log de transações aumentaria muito, mas se emitisse ALTER INDEX individualmente, o uso do espaço de log seria menor.

LT
fonte
0

A resposta anterior do Remus de que a indexação online requer 1,6x o tamanho do índice no modo de recuperação COMPLETO não está correta. A proporção de espaço de log de transações necessário para reconstruir um índice on-line em FULL pode ser muito maior e observamos muitas vezes o tamanho do índice, especialmente quando o índice que está sendo reconstruído é compactado, pois o log de transações não é compactado. Isso por si só deve deixar claro que o log de transações durante uma reconstrução on-line em COMPLETO pode ter pelo menos algumas vezes o tamanho do índice. Adicione uma sobrecarga de registro de tlog que não é totalmente documentada pela Microsoft, mas geralmente é estimada em 60 bytes por linha, e o tamanho proporcional do log durante uma reconstrução de índice online sob recuperação total pode ser muitas vezes o tamanho do índice que está sendo reconstruído, especialmente se o índice está compactado

Greg Linwood
fonte
-1

Rdfozz está correto, é a melhor maneira de decidir se seu maior índice pode ser reconstruído com base no armazenamento atual. Basta executar dm_exec_requestsenquanto a operação está acontecendo (ou SQL Profiler) para ver se todos os índices estão sendo reconstruídos. Também consideraria alterar o modelo de recuperação para o log em massa. É isso que eu faço e ainda existem backups de log de transações durante a janela. Veja abaixo o artigo https://technet.microsoft.com/en-us/library/ms191484(v=sql.105).aspx

ADTJOB
fonte
2
Observe que o OP declarou que seu banco de dados já está usando o modelo de recuperação SIMPLE; isso mantém apenas as transações no log por tempo suficiente para que as transações sejam concluídas. Não haveria melhoria se eles alternassem para logon em massa.
RDFozz
Você está certo. Me desculpe.
ADTJOB