Quando si modifica una colonna in NOT NULL, SQL Server deve toccare ogni singola pagina, anche se non sono presenti valori NULL. A seconda del fattore di riempimento, ciò potrebbe effettivamente comportare molte divisioni di pagina. Ogni pagina toccata, ovviamente, deve essere registrata e sospetto che, a causa delle divisioni, potrebbe essere necessario registrare due modifiche per molte pagine. Dato che è tutto fatto in un unico passaggio, tuttavia, il registro deve tenere conto di tutte le modifiche in modo che, se si preme Annulla, sappia esattamente cosa annullare.
Un esempio. Tavolo semplice:
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
Ora diamo un'occhiata ai dettagli della pagina. Per prima cosa dobbiamo scoprire con quale pagina e DB_ID abbiamo a che fare. Nel mio caso ho creato un database chiamato foo
e il DB_ID è risultato essere 5.
DBCC TRACEON(3604, -1);
DBCC IND('foo', 'dbo.floob', 1);
SELECT DB_ID();
L'output ha indicato che ero interessato a pagina 159 (l'unica riga DBCC IND
dell'output con PageType = 1
).
Ora diamo un'occhiata ad alcuni dettagli della pagina selezionata mentre esaminiamo lo scenario del PO.
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);
Ora, non ho tutte le risposte a questo, dato che non sono un tipo da interno profondo. Ma è chiaro che - mentre sia l'operazione di aggiornamento sia l'aggiunta del vincolo NOT NULL scrivono innegabilmente alla pagina - quest'ultima lo fa in un modo completamente diverso. Sembra effettivamente cambiare la struttura del record, piuttosto che giocherellare con i bit, scambiando la colonna nullable con una colonna non nullable. Perché debba farlo, non ne sono del tutto sicuro - una buona domanda per il team del motore di archiviazione , immagino. Credo che SQL Server 2012 gestisca alcuni di questi scenari molto meglio, FWIW - ma devo ancora fare test approfonditi.
NOT NULL
colonna con un valore predefinito come operazione di metadati. Vedere anche "Aggiunta di colonne NOT NULL come operazione online" nella documentazione .