有什么方法可以将列数据类型更改为仅元数据操作?
我不这么认为,这就是产品现在的工作方式。在Joe的答案中提出了一些非常好的解决此限制的方法。
...导致SQL Server重写整个表(并在日志空间中使用2x表大小)
我将分别回答该声明的两个部分。
重写表
如前所述,实际上没有任何方法可以避免这种情况。即使从我们作为客户的角度来看,这并不完全有意义,但这似乎是现实。
查看DBCC PAGE
将列从4000更改为260之前和之后,发现所有数据都在数据页面上重复(我的测试表'A'
在该行中有260次):
此时,页面上有两个完全相同的数据副本。本质上删除了“旧”列(将ID从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%)
如您所见,数据文件写入量略有下降,而日志文件写入量则有较大下降。