He encontrado varias fuentes que dicen ALTER TABLE ... DROP COLUMN es una operación solo de metadatos.
¿Cómo puede ser esto? ¿Los datos durante una COLUMNA DE GOTA no necesitan purgarse de los índices no agrupados subyacentes y del índice / montón agrupado?
Además, ¿por qué los documentos de Microsoft implican que es una operación completamente registrada?
Las modificaciones realizadas en la tabla se registran y son completamente recuperables. Los cambios que afectan a todas las filas en tablas grandes, como soltar una columna o, en algunas ediciones de SQL Server, agregar una columna NOT NULL con un valor predeterminado, pueden tardar mucho tiempo en completarse y generar muchos registros . Ejecute estas instrucciones ALTER TABLE con el mismo cuidado que cualquier instrucción INSERT, UPDATE o DELETE que afecte a muchas filas.
Como pregunta secundaria: ¿cómo realiza el motor el seguimiento de las columnas caídas si los datos no se eliminan de las páginas subyacentes?
fuente
Respuestas:
Hay ciertas circunstancias en las que soltar una columna puede ser una operación de metadatos solamente. Las definiciones de columna para cualquier tabla dada no se incluyen en todas y cada una de las páginas donde se almacenan las filas, las definiciones de columna solo se almacenan en los metadatos de la base de datos, incluidos sys.sysrowsets, sys.sysrscols, etc.
Al soltar una columna a la que ningún otro objeto hace referencia, el motor de almacenamiento simplemente marca la definición de la columna como que ya no está presente al eliminar los detalles pertinentes de varias tablas del sistema. La acción de eliminar los metadatos invalida el caché del procedimiento, lo que requiere una nueva compilación cada vez que una consulta hace referencia a esa tabla. Dado que la recompilación solo devuelve columnas que existen actualmente en la tabla, los detalles de la columna eliminada nunca se solicitan; el motor de almacenamiento omite los bytes almacenados en cada página para esa columna, como si la columna ya no existiera.
Cuando se produce una operación DML posterior en la tabla, las páginas afectadas se vuelven a escribir sin los datos de la columna descartada. Si reconstruye un índice agrupado o un montón, naturalmente, todos los bytes de la columna descartada no se vuelven a escribir en la página del disco. Esto efectivamente extiende la carga de soltar la columna con el tiempo, haciéndola menos notable.
Hay circunstancias en las que no puede soltar una columna, como cuando la columna se incluye en un índice o cuando ha creado manualmente un objeto de estadísticas para la columna. Escribí una publicación de blog que muestra el error que se presenta al intentar alterar una columna con un objeto de estadísticas creado manualmente. La misma semántica se aplica cuando se suelta una columna: si la columna es referenciada por cualquier otro objeto, simplemente no se puede soltar. El objeto de referencia debe modificarse primero, luego la columna puede descartarse.
Esto es bastante fácil de mostrar al mirar el contenido del registro de transacciones después de soltar una columna. El siguiente código crea una tabla con una sola columna de caracteres largos de 8,000. Agrega una fila, luego la descarta y muestra el contenido del registro de transacciones aplicable a la operación de descarte. Los registros de anotaciones muestran modificaciones en varias tablas del sistema donde se almacenan las definiciones de tabla y columna. Si los datos de la columna realmente se eliminaran de las páginas asignadas a la tabla, vería registros que registran los datos reales de la página; No hay tales registros.
(El resultado es demasiado grande para mostrar aquí, y dbfiddle.uk no me permite acceder a fn_dblog)
El primer conjunto de resultados muestra el registro como resultado de que la instrucción DDL descarte la columna. El segundo conjunto de resultados muestra el registro después de ejecutar la instrucción DML donde actualizamos la
rid
columna. En el segundo conjunto de resultados, vemos registros que indican una eliminación de dbo.DropColumnTest, seguido de una inserción en dbo.DropColumnTest. La longitud de cada registro es 8116, lo que indica que se actualizó la página real.Como puede ver en la salida del
fn_dblog
comando en la prueba anterior, toda la operación está completamente registrada. Esto se aplica a la recuperación simple, así como a la recuperación completa. La terminología "totalmente registrada" puede malinterpretarse ya que la modificación de datos no se registra. Esto no es lo que sucede: la modificación se registra y se puede revertir por completo. El registro es simplemente única grabando las páginas que fueron tocados, y puesto que ninguno de los datos en las páginas de la tabla se registra por la operación DDL, tanto elDROP COLUMN
, y cualquier reversión que pudiera ocurrir ocurrirá de forma extremadamente rápida, sin importar el tamaño de la tabla.Para ciencia , el siguiente código volcará las páginas de datos para la tabla incluida en el código anterior, usando el
DBCC PAGE
estilo "3". El estilo "3" indica que queremos el encabezado de página más la interpretación detallada por fila . El código usa un cursor para mostrar los detalles de cada página de la tabla, por lo que es posible que desee asegurarse de no ejecutar esto en una tabla grande.Mirando el resultado de la primera página de mi demo (después de que se suelta la columna, pero antes de que la columna se actualice), veo esto:
He eliminado la mayor parte del volcado de página sin procesar del resultado que se muestra arriba por brevedad. Al final de la salida, verá esto para la
rid
columna:La última línea anterior,
rid = 1
devuelve el nombre de la columna y el valor actual almacenado en la columna de la página.A continuación, verás esto:
El resultado muestra que la ranura 0 contiene una columna eliminada, en virtud del
DELETED
texto donde normalmente estaría el nombre de la columna. El valor de la columna se devuelveNULL
ya que la columna se ha eliminado. Sin embargo, como puede ver en los datos sin procesar, el valor largo de 8,000 caracteresREPLICATE('Z', 8000)
para esa columna todavía existe en la página. Esta es una muestra de esa parte de la salida de DBCC PAGE:fuente