SQL Server 2016+ 整数类型元数据扩宽(秒级变更)完整说明
一、核心前提:必须启用压缩
只有在表的所有索引和所有分区都已启用 ROW 或 PAGE 压缩时 ,以下整数类型扩宽才能以纯元数据方式完成(几乎瞬间、不重写数据页):
smallint→int或bigintint→bigintsmallmoney→money
测试结论非常明确:
- 已启用压缩 →
int→bigint可秒级完成(纯元数据操作)。 - 未启用压缩 → 必须先把所有索引重建为压缩模式,耗时很长(尤其大表),之后才能做元数据变更。
- 即使已启用压缩,
tinyint→smallint也不会 秒级完成(tinyint是无符号类型,底层存储格式不兼容)。 - 缩小类型(如
bigint→int)即使已压缩,也需要完整数据重写,用时通常更久(还可能因数据溢出而失败)。
二、完整前提条件清单(缺一不可)
- SQL Server 版本 ≥ 2016
- 压缩要求 (最关键)
所有索引(聚集 + 非聚集)+ 所有分区 的data_compression_desc必须全部是ROW或PAGE(可混合),不能有任何NONE。 - 支持的类型变更
- 整数:
smallint→int/bigint、int→bigint - 货币:
smallmoney→money - 字符串/二进制:
char(n)→char(m)或varchar(m)(n < m且m ≠ max),nchar/binary同理 - 不支持 :
tinyint任何扩宽、缩小类型、可空 → 非空
- 整数:
- 表类型:必须是 rowstore(非 columnstore)
- 不能同时修改可空性(NULL → NOT NULL 会强制数据扫描)
三、如何检查表是否满足压缩前提
执行以下查询(把表名换成实际表名):
sql
SELECT
OBJECT_SCHEMA_NAME(p.object_id) AS SchemaName,
OBJECT_NAME(p.object_id) AS TableName,
i.name AS IndexName,
i.type_desc AS IndexType,
p.partition_number,
p.rows,
p.data_compression, -- 0=NONE, 1=ROW, 2=PAGE, 3=COLUMNSTORE 等
p.data_compression_desc -- NONE / ROW / PAGE / COLUMNSTORE 等
FROM sys.partitions p
INNER JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
WHERE p.object_id = OBJECT_ID(N'dbo.sample_table') -- 替换为实际表名(含 schema)
ORDER BY i.index_id, p.partition_number;
判断标准:
- 所有行的
data_compression_desc都是ROW或PAGE→ 满足条件,可直接做元数据变更。 - 任意一行是
NONE→ 不满足,必须先重建压缩。
四、实际测试结论总结
| 场景 | 是否启用压缩 | 结果说明 | 预估耗时(大表) |
|---|---|---|---|
int → bigint |
是 | 纯元数据操作,秒级完成 | 秒级 |
int → bigint |
否 | 必须先重建所有索引为压缩模式,再变更 | 非常久(小时级) |
bigint → int(缩小) |
是/否 | 必须重写数据 + 可能数据溢出检查,用时更久 | 更久 |
tinyint → smallint |
是 | 不支持元数据方式(无符号 vs 有符号) | 完整数据重写 |
| 可空 → 非空 | 任意 | 强制扫描数据,无法纯元数据 | 完整数据重写 |
五、推荐操作流程(想做秒级变更时)
- 用上面的查询确认压缩状态。
- 如果存在
NONE,先统一启用压缩(建议维护窗口执行):
sql
-- 示例:整表重建为 PAGE 压缩(Enterprise/Developer 可用 ONLINE)
ALTER TABLE dbo.sample_table
REBUILD WITH (DATA_COMPRESSION = PAGE, ONLINE = ON);
或按索引逐个重建。
- 再次用查询确认全部为
ROW/PAGE。 - 执行类型变更:
sql
ALTER TABLE dbo.sample_table
ALTER COLUMN 你的列名 bigint NOT NULL; -- 或其他支持的扩宽
此时才会真正实现秒级元数据变更。
总结 :
能否「秒完成」栏位扩宽,核心取决于该表所有索引是否已全部启用 ROW/PAGE 压缩。未启用时先重建压缩的成本往往远高于直接改类型,需提前规划。