Existe alguma maneira de alterar o tipo de dados da coluna como uma operação somente de metadados?
Acho que não, é assim que o produto funciona agora. Existem algumas soluções realmente ótimas para essa limitação proposta na resposta de Joe .
... resulta no SQL Server reescrevendo a tabela inteira (e usando o tamanho da tabela 2x no espaço de log)
Vou responder às duas partes dessa declaração separadamente.
Reescrevendo a Tabela
Como mencionei antes, não há realmente nenhuma maneira de evitar isso. Essa parece ser a realidade da situação, mesmo que não faça todo o sentido da nossa perspectiva como clientes.
Observar DBCC PAGE
antes e depois de alterar a coluna de 4000 para 260 mostra que todos os dados são duplicados na página de dados (minha tabela de teste teve 'A'
260 vezes na linha):
Neste ponto, há duas cópias exatamente dos mesmos dados na página. A coluna "antiga" é essencialmente excluída (a identificação é alterada de id = 2 para id = 67108865) e a versão "nova" da coluna é atualizada para apontar para o novo deslocamento dos dados na página:
Usando 2x o tamanho da tabela no espaço de log
A adição WITH (ONLINE = ON)
ao final da ALTER
instrução reduz a atividade de registro em cerca de metade . Portanto, esse é um aprimoramento que você pode fazer para reduzir a quantidade de gravações necessárias no espaço em disco / disco.
Eu usei este equipamento de teste para testá-lo:
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
Eu verifiquei sys.dm_io_virtual_file_stats(DB_ID(N'248749'), DEFAULT)
antes e depois de executar a ALTER
instrução, e aqui estão as diferenças:
Padrão (offline) ALTER
- Gravações no arquivo de dados / bytes gravados: 34.809 / 2.193.801.216
- Gravações no arquivo de log / bytes gravados: 40.953 / 1.484.910.080
Conectados ALTER
- Gravações no arquivo de dados / bytes gravados: 36.874 / 1.693.745.152 (queda de 22,8%)
- Gravações do arquivo de log / bytes gravados: 24.680 / 866.166.272 (queda de 41%)
Como você pode ver, houve uma pequena queda nas gravações do arquivo de dados e uma grande queda nas gravações do arquivo de log.