¿ALTER INDEX ALL REBUILD usa más espacio de registro de transacciones con un modelo de recuperación simple que la reconstrucción de cada índice individualmente?

18

Error en la operación "ALTERAR ÍNDICE TODO RECONSTRUCCIÓN" en SQL Server 2012 porque el registro de transacciones se quedó sin espacio. Los índices nunca se han reorganizado o reconstruido, por lo que la fragmentación supera el 80% en casi todos.

El DB utiliza un modelo de recuperación simple. Supuse que después de cada operación de índice realizada por la forma "TODO" del comando, los datos del registro de transacciones se eliminarían antes de la próxima reconstrucción del índice. ¿Es así como funciona realmente, o las reconstrucciones de índice se registran como si fueran parte de una sola transacción?

En otras palabras, ¿podría reducir el crecimiento del registro de transacciones escribiendo un script para realizar cada reconstrucción individualmente? ¿Hay otros factores a considerar?

Google Fail
fuente
2
Salvo que los datos explícitos indiquen lo contrario, supondría que un comando SQL específico sería considerado una transacción atómica única por el motor DB. En este caso, puede probar la teoría con bastante facilidad. Tome su índice más grande e intente reconstruirlo. Si eso tiene éxito, entonces es razonable suponer que el registro está acumulando información de múltiples reconstrucciones. Si falla, debe agregar espacio para el registro (ya que tiene un problema de cualquier manera), o debe intentar reorganizar ese índice, en lugar de reconstruirlo (si no puede aumentar el espacio para el t- Iniciar sesión).
RDFozz
Sí, ese pensamiento se me ocurrió justo cuando terminé de escribir esto (efecto pato de goma), pero pensé que sería mejor obtener confirmación y dejarlo en manos de otros que podrían pensar de la misma manera. No quiero experimentar con este entorno, por lo que probablemente terminaré agregando espacio a los registros de cualquier manera.
Google Fail

Respuestas:

16

Supuse que después de cada operación de índice realizada por la forma "TODO" del comando, los datos del registro de transacciones se eliminarían antes de la próxima reconstrucción del índice. ¿Es así como funciona realmente, o las reconstrucciones de índice se registran como si fueran parte de una sola transacción?

1) Descarga de registros: el modelo de recuperación SIMPLE no borra el registro después de cada transacción, sino en los puntos de control. ( enlace para más información)

2a) REBUILD ALL: sí, REBUILD ALL funciona como una sola transacción. Las reconstrucciones de índice dentro tienen sus propias transacciones, pero la operación general no se confirma por completo hasta el final. Entonces, sí, puede limitar el crecimiento del archivo de registro reconstruyendo índices individuales (y posiblemente emitiendo comandos CHECKPOINT).

2b) ¡Prueba! Aquí, tenga un script de demostración. (Construido en 2016 dev) Primero, configure una base de datos de prueba, con tabla 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')

Ahora puede comparar la actividad de registro entre REBUILD ALL y 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 cómo la primera transacción abierta (ID de transacción 0000: 000002fa para mí) no se confirma hasta el final de REBUILD ALL, pero para las reconstrucciones de índice por índice, se confirman sucesivamente.

Para descanso
fuente
¡Guau, gracias por la respuesta realmente detallada! Esa es una excelente manera de ver lo que sucede debajo del capó, por así decirlo.
Google Fail
Bien explicado.
Ramakant Dadhichi
4

Tal como está, esta es una transacción única.

Pedro Lopes
fuente
66
Bienvenido a DBA.SE! En general, las mejores respuestas no son afirmaciones simples, sino que están respaldadas por información de documentación o artículos, o (a menudo incluso mejor) experiencia personal que demuestra la respuesta indicada. ¿Puede ampliar su respuesta para proporcionar ese tipo de respaldo?
RDFozz
2
@RDFozz Comentario justo, pero ¿miraste el perfil de Pedro ? El acceso al código fuente probablemente se puede considerar más autorizado que la experiencia personal o la documentación. :-)
Aaron Bertrand
3
@AaronBertrand - Lo confieso, no lo hice. Ciertamente pensaría que ser parte del equipo de SQL Server realmente calificaría. Aún así, vale la pena hacer referencia a eso en la respuesta. +1, en cualquier caso.
RDFozz
3

La pregunta es trivial para una reconstrucción sin conexión . Por supuesto es una sola transacción. Imagine el caos que se produciría si la operación dividiera cada índice en su propia transacción, ya que tendría que liberar los bloqueos al confirmar y luego volver a adquirirlos. Si bien se liberó el bloqueo de la tabla crítica SCH-M, se pueden descartar índices y se pueden crear nuevos índices, ¿cómo manejaría la declaración tales casos? ¡Sin mencionar que la tabla puede descartarse e incluso volver a crearse entre las dos transacciones! Incluyendo el caso cuando la tabla se cae y se crea una tabla diferente con la misma identificación de objeto (sí, puede suceder) ...

¿Qué sucede si aumenta la pregunta para decir qué sucede si la reconstrucción del índice es en línea? reconstrucción en ? ¿Es una sola transacción o muchas? La respuesta es compleja, ya que en realidad hay varias transacciones internas involucradas . Sin embargo, el punto clave es que hay una transacción de archivado general que abarca toda la operación (la declaración ALTER) y esto fija el registro en su lugar (no se puede truncar), por lo tanto, la operación debe planificarse en consecuencia para permitir ~ 1.6x datos tamaño para el modo de recuperación COMPLETA, o tamaño de datos 0.2x para el modo BULK_LOGGED / SIMPLE. Vea el documento vinculado para más detalles.

Puede argumentar que ¿por qué la compilación fuera de línea no emplea las mismas transacciones internas que el modo en línea y divide la operación? Los problemas que mencioné sobre la alteración / caída de la tabla entre las operaciones de índice individuales (es decir, la "estabilidad del esquema" de la tabla) aún requerirían que haya una transacción global que mantenga un SCH-S en la tabla durante toda la duración de la declaración. Dado que esta transacción también debe contener el SCH-S durante la recuperación, debe registrarse y, como tal, habrá un registro de registro BEGIN XACT que fijará el registro y evitará el truncamiento durante toda la declaración. Sé que este problema en particular se estaba abordando en el marco de tiempo SQL 2016-2017 (debido a problemas de tamaño de registro de SQL Azure), pero no estoy seguro de qué progreso se hizo . Parece que ahora está en la vista previa:La reconstrucción de índice en línea reanudable está en una vista previa pública para SQL Server 2017 CTP 2.0 .

Remus Rusanu
fuente
0

Sí, tuve el mismo problema con una mesa muy grande. Cada vez que emitía ALTER INDEX ALL, el registro de transacciones crecería mucho, pero si se emitía ALTER INDEX individualmente, el uso del espacio de registro sería menor.

LT
fuente
0

La respuesta anterior de Remus de que la indexación en línea requiere 1,6 veces el tamaño del índice en el modo de recuperación COMPLETA no es correcta. La proporción del espacio de registro de transacciones requerido para reconstruir un índice en línea bajo COMPLETO puede ser mucho mayor y hemos observado muchas veces el tamaño del índice, especialmente cuando el índice que se está reconstruyendo se comprime porque el registro de transacciones no se comprime. Esto solo debería dejar en claro que el registro de transacciones durante una reconstrucción en línea bajo COMPLETO puede ser al menos unas veces el tamaño del índice. Agregue una sobrecarga de registro de tlog que no está completamente documentada por Microsoft, pero a menudo se estima en 60 bytes por fila y el tamaño proporcional del registro durante una reconstrucción de índice en línea bajo recuperación completa puede ser muchas veces el tamaño del índice que se está reconstruyendo, especialmente si el índice está comprimido

Greg Linwood
fuente
-1

Rdfozz es correcto, esa es la mejor manera de decidir si su índice más grande puede reconstruirse en función del almacenamiento actual. Simplemente ejecute dm_exec_requestsmientras se realiza la operación (o SQL Profiler) para ver si se están reconstruyendo todos los índices. También consideraría cambiar el modelo de recuperación a registro masivo. Esto es lo que hago y todavía hay copias de seguridad del registro de transacciones durante la ventana. Vea a continuación el artículo https://technet.microsoft.com/en-us/library/ms191484(v=sql.105).aspx

ADTJOB
fuente
2
Tenga en cuenta que el OP declaró que su base de datos ya está utilizando el modelo de recuperación SIMPLE; esto solo mantiene las transacciones en el registro el tiempo suficiente para que se completen las transacciones. No habría ninguna mejora si cambiaran a registro masivo.
RDFozz
Tienes toda la razón. Mis disculpas.
ADTJOB