Cuando cambia una columna a NOT NULL, SQL Server tiene que tocar cada página, incluso si no hay valores NULL. Dependiendo de su factor de relleno, esto podría conducir a muchas divisiones de página. Cada página que se toca, por supuesto, debe registrarse, y sospecho que debido a las divisiones, es posible que se deban registrar dos cambios para muchas páginas. Sin embargo, dado que todo se hace en una sola pasada, el registro debe tener en cuenta todos los cambios para que, si presiona cancelar, sepa exactamente qué deshacer.
Un ejemplo. Tabla simple:
DROP TABLE dbo.floob;
GO
CREATE TABLE dbo.floob
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
bar INT NULL
);
INSERT dbo.floob(bar) SELECT NULL UNION ALL SELECT 4 UNION ALL SELECT NULL;
ALTER TABLE dbo.floob ADD CONSTRAINT df DEFAULT(0) FOR bar
Ahora, veamos los detalles de la página. Primero tenemos que averiguar qué página y DB_ID estamos tratando. En mi caso, creé una base de datos llamada foo
y el DB_ID resultó ser 5.
DBCC TRACEON(3604, -1);
DBCC IND('foo', 'dbo.floob', 1);
SELECT DB_ID();
La salida indicaba que estaba interesado en la página 159 (la única fila en la DBCC IND
salida con PageType = 1
).
Ahora, veamos algunos detalles de la página seleccionada a medida que avanzamos por el escenario del OP.
DBCC PAGE(5, 1, 159, 3);
UPDATE dbo.floob SET bar = 0 WHERE bar IS NULL;
DBCC PAGE(5, 1, 159, 3);
ALTER TABLE dbo.floob ALTER COLUMN bar INT NOT NULL;
DBCC PAGE(5, 1, 159, 3);
Ahora, no tengo todas las respuestas a esto, ya que no soy un tipo interno profundo. Pero está claro que, si bien tanto la operación de actualización como la adición de la restricción NOT NULL, sin lugar a dudas, escriben en la página, este último lo hace de una manera completamente diferente. Parece que en realidad cambia la estructura del registro, en lugar de solo jugar con bits, cambiando la columna anulable por una columna no anulable. Por qué tiene que hacer eso, no estoy muy seguro: una buena pregunta para el equipo del motor de almacenamiento , supongo. Creo que SQL Server 2012 maneja algunos de estos escenarios mucho mejor, FWIW, pero todavía tengo que hacer pruebas exhaustivas.
NOT NULL
columna con una operación predeterminada como metadatos. Consulte también "Agregar columnas NO NULL como una operación en línea" en la documentación .