Есть ли способ изменить тип данных столбца как операцию только для метаданных?
Я так не думаю, вот как продукт работает прямо сейчас. В ответе Джо есть несколько действительно хороших способов обойти это ограничение .
... в результате SQL Server переписывает всю таблицу (и использует 2x размер таблицы в пространстве журнала)
Я собираюсь ответить на две части этого заявления отдельно.
Переписывая таблицу
Как я упоминал ранее, на самом деле нет никакого способа избежать этого. Кажется, что это реальность ситуации, даже если она не имеет полного смысла с нашей точки зрения как клиентов.
Просмотр DBCC PAGE
до и после изменения столбца с 4000 на 260 показывает, что все данные дублируются на странице данных (моя тестовая таблица имела 'A'
260 строк подряд):
На данный момент на странице есть две копии абсолютно одинаковых данных. «Старый» столбец по существу удаляется (идентификатор изменяется с id = 2 на id = 67108865), а «новая» версия столбца обновляется, чтобы указывать на новое смещение данных на странице:
Использование 2x размера таблицы в пространстве журнала
Добавление WITH (ONLINE = ON)
в конец ALTER
оператора сокращает активность журналирования примерно вдвое , поэтому это одно из улучшений, которое вы можете сделать, чтобы уменьшить количество операций записи на диск / дисковое пространство, необходимое.
Я использовал этот тестовый жгут, чтобы опробовать его:
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
Я проверил sys.dm_io_virtual_file_stats(DB_ID(N'248749'), DEFAULT)
до и после запуска ALTER
оператора, и вот различия:
По умолчанию (в автономном режиме) ALTER
- Запись в файл данных / записано байтов: 34 809/2 193 801 216
- Записывает в файл журнала / записано байтов: 40,953 / 1,484,910,080
В сети ALTER
- Запись в файл данных / записанных байтов: 36 874/1 693 745 152 (падение на 22,8%)
- Записывает в файл журнала / записано байтов: 24,680 / 866,166,272 (падение на 41%)
Как вы можете видеть, произошло небольшое снижение количества записей в файле данных и значительное падение в записи файла журнала.