Ответ @ ypercube справляется с этим частично только из-за изменения метаданных.
Добавление ограничения NOCHECK
означает, что для его проверки не нужно читать строки, и если вы начинаете с позиции, в которой столбец не содержит NULL
значений (и если вы знаете, что между проверкой и добавлением ограничения не будет добавлено ни одной), поскольку ограничение предотвращает NULL
создание значений из будущего INSERT
или UPDATE
операций, это будет работать.
Однако добавление ограничения может повлиять на одновременные транзакции. ALTER TABLE
Нужно будет приобрести Sch-M
замок первым. Пока он ожидает этого, все другие обращения к таблице будут заблокированы, как описано здесь .
Однако после того, как Sch-M
блокировка получена, операция должна быть довольно быстрой.
Одна из проблем заключается в том, что даже если вы знаете, что в столбце фактически нет NULL
s, оптимизатор запросов не доверяет ограничению, что означает, что планы могут быть неоптимальными.
CREATE TABLE T (X INT NULL)
INSERT INTO T
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values
ALTER TABLE T WITH NOCHECK
ADD CONSTRAINT X_NOT_NULL
CHECK (X IS NOT NULL) ;
SELECT *
FROM T
WHERE X NOT IN (SELECT X FROM T)
Сравните это с более простым
ALTER TABLE T ALTER COLUMN X INT NOT NULL
SELECT *
FROM T
WHERE X NOT IN (SELECT X FROM T)
Одна из возможных проблем, с которой вы можете столкнуться при изменении определения столбца таким образом, заключается в том, что он не только должен прочитать все строки, чтобы убедиться, что они удовлетворяют условию, но также может в конечном итоге выполнить записанные обновления строк .
Возможно, на полпути можно добавить ограничение проверки WITH CHECK
. Это будет медленнее, чем WITH NOCHECK
нужно для чтения всех строк, но это позволяет оптимизатору запросов дать более простой план в запросе выше, и это должно избежать возможной проблемы с записанными обновлениями.