Nic*_*ley 13 sql-server alter-table sql-server-2017
我有一个性能问题,非常大的内存授予处理这个包含几NVARCHAR(4000)列的表。事情是这些列永远不会大于NVARCHAR(260).
使用
ALTER TABLE [table] ALTER COLUMN [col] NVARCHAR(260) NULL
Run Code Online (Sandbox Code Playgroud)
导致 SQL Server 重写整个表(并在日志空间中使用 2 倍的表大小),这是数十亿行,只是什么都不改变,不是一个选项。增加列宽没有这个问题,但减少它。
我曾尝试创建约束CHECK (DATALENGTH([col]) <= 520)或CHECK (LEN([col]) <= 260)SQL Server 仍然决定重写整个表。
有没有办法将列数据类型更改为仅限元数据的操作?无需重写整个表?我使用的是 SQL Server 2017(14.0.2027.2 和 14.0.3192.2)。
这是用于重现的示例 DDL 表:
CREATE TABLE [table](
id INT IDENTITY(1,1) NOT NULL,
[col] NVARCHAR(4000) NULL,
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED (id ASC)
);
Run Code Online (Sandbox Code Playgroud)
然后运行ALTER.
Joe*_*ish 16
我不知道有什么方法可以直接完成您在这里寻找的内容。请注意,此时查询优化器不够智能,无法将内存授予计算的约束因素考虑在内,因此无论如何该约束都无济于事。一些避免重写表数据的方法:
Jos*_*ell 16
有没有办法将列数据类型更改为仅限元数据的操作?
我不这么认为,这就是产品现在的工作方式。对于Joe's answer 中提出的这个限制,有一些非常好的解决方法。
...导致 SQL Server 重写整个表(并在日志空间中使用 2x 表大小)
我将分别回应该声明的两个部分。
正如我之前提到的,实际上没有任何方法可以避免这种情况。这似乎是现实情况,即使从我们作为客户的角度来看,这并不完全合理。
查看DBCC PAGE将列从 4000 更改为 260 之前和之后显示所有数据都在数据页上重复(我的测试表'A'在该行中有260 次):
此时,页面上有两份完全相同的数据。“旧”列本质上被删除(id从id=2改为id=67108865),更新“新”版本的列,指向页面上数据的新偏移量:
添加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
Run Code Online (Sandbox Code Playgroud)
我sys.dm_io_virtual_file_stats(DB_ID(N'248749'), DEFAULT)在运行ALTER语句之前和之后进行了检查,以下是差异:
ALTERALTER如您所见,数据文件写入略有下降,日志文件写入大幅下降。
| 归档时间: |
|
| 查看次数: |
740 次 |
| 最近记录: |