Odpowiedź @ ypercube radzi sobie z tym częściowo, ponieważ zmienia się tylko metadane.
Dodanie ograniczenia NOCHECK
oznacza, że żadne wiersze nie będą musiały być czytane, aby je zweryfikować, a jeśli zaczynasz od pozycji, w której kolumna nie zawiera NULL
wartości (i jeśli wiesz, że żaden nie zostanie dodany między sprawdzaniem a dodawaniem ograniczenia), ponieważ ograniczenie uniemożliwia tworzenie NULL
wartości z przyszłości INSERT
lub UPDATE
operacji, to zadziała.
Dodanie ograniczenia może jednak mieć wpływ na współbieżne transakcje. ALTER TABLE
Będą musiały nabyć Sch-M
blokadę pierwszy. Podczas oczekiwania na to wszystkie inne dostęp do tabeli zostaną zablokowane, jak opisano tutaj .
Po uzyskaniu Sch-M
blokady operacja powinna być jednak dość szybka.
Jednym z problemów jest to, że nawet jeśli wiesz, że kolumna w rzeczywistości nie ma żadnych NULL
ograniczeń, optymalizator zapytań nie ufa temu ograniczeniu, co oznacza, że plany mogą być nieoptymalne.
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)
Porównaj to z prostszym
ALTER TABLE T ALTER COLUMN X INT NOT NULL
SELECT *
FROM T
WHERE X NOT IN (SELECT X FROM T)
Jednym z możliwych problemów, które możesz napotkać podczas zmiany definicji kolumny w ten sposób, jest to, że musi on nie tylko odczytać wszystkie wiersze, aby sprawdzić, czy spełniają warunek, ale może także faktycznie wykonać zarejestrowane aktualizacje wierszy .
Możliwym rozwiązaniem w połowie drogi może być dodanie ograniczenia sprawdzania WITH CHECK
. Będzie to wolniejsze niż WITH NOCHECK
w przypadku konieczności odczytu wszystkich wierszy, ale pozwala optymalizatorowi zapytań podać prostszy plan w powyższym zapytaniu i powinno unikać potencjalnego problemu z zalogowanymi aktualizacjami.