Когда вы изменяете столбец на NOT NULL, SQL Server должен касаться каждой отдельной страницы, даже если значения NULL отсутствуют. В зависимости от вашего коэффициента заполнения это может привести к большому количеству страниц. Конечно, каждая затронутая страница должна регистрироваться, и я подозреваю, что из-за разделения на двух страницах может потребоваться регистрация двух изменений. Так как все это делается за один проход, журнал должен учитывать все изменения, поэтому, если вы нажмете «Отмена», он точно знает, что нужно отменить.
Пример. Простая таблица:
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
Теперь давайте посмотрим на детали страницы. Для начала нам нужно выяснить, с какой страницей и DB_ID мы имеем дело. В моем случае я создал базу данных с именем foo
, а DB_ID оказался равным 5.
DBCC TRACEON(3604, -1);
DBCC IND('foo', 'dbo.floob', 1);
SELECT DB_ID();
Вывод показал, что меня заинтересовала страница 159 (единственная строка в DBCC IND
выводе с PageType = 1
).
Теперь давайте посмотрим на некоторые детали страницы, пока мы шагаем по сценарию ОП.
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);
Теперь у меня нет ответов на все вопросы, так как я не глубоко внутренний парень. Но ясно, что - хотя операция обновления и добавление ограничения NOT NULL, несомненно, записывают на страницу - последняя делает это совершенно по-другому. Похоже, что это на самом деле меняет структуру записи, а не просто возится с битами, заменяя обнуляемый столбец на ненулевой столбец. Почему я должен это делать, я не совсем уверен - наверное, хороший вопрос для команды разработчиков хранилищ . Я верю, что SQL Server 2012 справляется с некоторыми из этих сценариев намного лучше, FWIW - но я еще не провел какого-либо исчерпывающего тестирования.
NOT NULL
столбец со значением по умолчанию в качестве операции метаданных. Также см. «Добавление столбцов NOT NULL в качестве оперативной операции» в документации .