Esiste un modo per modificare il tipo di dati della colonna come un'operazione di soli metadati?
Non credo, ecco come funziona il prodotto in questo momento. Ci sono alcune soluzioni davvero eccezionali a questa limitazione proposta nella risposta di Joe .
... comporta la riscrittura di tutta la tabella in SQL Server (e l'utilizzo di 2x dimensioni della tabella nello spazio di registro)
Risponderò alle due parti di quella dichiarazione separatamente.
Riscrivere la tabella
Come ho detto prima, non c'è davvero alcun modo per evitarlo. Questa sembra essere la realtà della situazione, anche se non ha completamente senso dalla nostra prospettiva di clienti.
Guardare DBCC PAGE
prima e dopo aver modificato la colonna da 4000 a 260 mostra che tutti i dati sono duplicati nella pagina dei dati (la mia tabella di test aveva 'A'
260 volte nella riga):
A questo punto, ci sono due copie degli stessi identici dati sulla pagina. La colonna "vecchia" viene sostanzialmente eliminata (l'id viene cambiato da id = 2 a id = 67108865) e la "nuova" versione della colonna viene aggiornata per puntare al nuovo offset dei dati nella pagina:
Utilizzo di 2x dimensioni tabella nello spazio registro
L'aggiunta WITH (ONLINE = ON)
alla fine ALTER
dell'istruzione riduce l'attività di registrazione di circa la metà , quindi questo è un miglioramento che potresti apportare per ridurre la quantità di scritture sullo spazio su disco / disco necessario.
Ho usato questo cablaggio di prova per provarlo:
USE [master];
GO
DROP DATABASE IF EXISTS [248749];
GO
CREATE DATABASE [248749]
ON PRIMARY
(
NAME = N'248749',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\DATA\248749.mdf',
SIZE = 2048000KB,
FILEGROWTH = 65536KB
)
LOG ON
(
NAME = N'248749_log',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\DATA\248749_log.ldf',
SIZE = 2048000KB,
FILEGROWTH = 65536KB
);
GO
USE [248749];
GO
CREATE TABLE dbo.[table]
(
id int IDENTITY(1,1) NOT NULL,
[col] nvarchar (4000) NULL,
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED (id ASC)
);
INSERT INTO dbo.[table]
SELECT TOP (1000000)
REPLICATE(N'A', 260)
FROM master.dbo.spt_values v1
CROSS JOIN master.dbo.spt_values v2
CROSS JOIN master.dbo.spt_values v3;
GO
Ho controllato sys.dm_io_virtual_file_stats(DB_ID(N'248749'), DEFAULT)
prima e dopo l'esecuzione ALTER
dell'istruzione e qui ci sono le differenze:
Predefinito (offline) ALTER
- Scritture / byte di file di dati scritti: 34.809 / 2.193.801.216
- Scritture / byte del file di registro scritti: 40.953 / 1.484.910.080
in linea ALTER
- Scritture / byte di file di dati scritti: 36.874 / 1.693.745.152 (calo del 22,8%)
- Scritture / byte di file di registro scritti: 24.680 / 866.166.272 (calo del 41%)
Come puoi vedere, c'è stata una leggera caduta nelle scritture dei file di dati e una forte caduta nelle scritture dei file di registro.