Existe-t-il un moyen de modifier le type de données de colonne en tant qu'opération de métadonnées uniquement?
Je ne pense pas, c'est ainsi que fonctionne le produit en ce moment. Il existe de très bonnes solutions de contournement à cette limitation proposée dans la réponse de Joe .
... entraîne la réécriture de SQL Server de la table entière (et l'utilisation d'une taille de table 2x dans l'espace de journal)
Je vais répondre séparément aux deux parties de cette déclaration.
Réécrire la table
Comme je l'ai mentionné précédemment, il n'y a vraiment aucun moyen d'éviter cela. Cela semble être la réalité de la situation, même si cela n'a pas de sens de notre point de vue en tant que clients.
Regarder DBCC PAGE
avant et après avoir changé la colonne de 4000 en 260 montre que toutes les données sont dupliquées sur la page de données (ma table de test avait 'A'
260 fois de suite):
À ce stade, il existe deux copies des mêmes données exactes sur la page. La "vieille" colonne est essentiellement supprimée (l'ID est changé de id = 2 à id = 67108865), et la "nouvelle" version de la colonne est mise à jour pour pointer vers le nouveau décalage des données sur la page:
Utilisation de la taille de table 2x dans l'espace de journal
L'ajout WITH (ONLINE = ON)
à la fin de l' ALTER
instruction réduit l'activité de journalisation d'environ la moitié , c'est donc une amélioration que vous pourriez apporter pour réduire la quantité d'écritures sur le disque / l'espace disque nécessaire.
J'ai utilisé ce harnais de test pour l'essayer:
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
J'ai vérifié sys.dm_io_virtual_file_stats(DB_ID(N'248749'), DEFAULT)
avant et après l'exécution de l' ALTER
instruction, et voici les différences:
Par défaut (hors ligne) ALTER
- Écriture du fichier de données / octets écrits: 34,809 / 2,193,801,216
- Écriture du fichier journal / octets écrits: 40,953 / 1,484,910,080
En ligne ALTER
- Écriture du fichier de données / octets écrits: 36 874/1 693 745 152 (baisse de 22,8%)
- Écrits du fichier journal / octets écrits: 24,680 / 866,166,272 (baisse de 41%)
Comme vous pouvez le voir, il y a eu une légère baisse des écritures du fichier de données et une baisse importante des écritures du fichier journal.