SQL Server 2016+ 整数类型元数据扩宽(秒级变更)完整说明

SQL Server 2016+ 整数类型元数据扩宽(秒级变更)完整说明

一、核心前提:必须启用压缩

只有在表的所有索引和所有分区都已启用 ROW 或 PAGE 压缩时 ,以下整数类型扩宽才能以纯元数据方式完成(几乎瞬间、不重写数据页):

  • smallint → int 或 bigint
  • int → bigint
  • smallmoney → money

测试结论非常明确:

  • 已启用压缩 → int → bigint 可秒级完成(纯元数据操作)。
  • 未启用压缩 → 必须先把所有索引重建为压缩模式,耗时很长(尤其大表),之后才能做元数据变更。
  • 即使已启用压缩,tinyint → smallint 也不会 秒级完成(tinyint 是无符号类型,底层存储格式不兼容)。
  • 缩小类型(如 bigint → int)即使已压缩,也需要完整数据重写,用时通常更久(还可能因数据溢出而失败)。

二、完整前提条件清单(缺一不可)

  1. SQL Server 版本 ≥ 2016
  2. 压缩要求 (最关键)
    所有索引(聚集 + 非聚集)+ 所有分区 的 data_compression_desc 必须全部是 ROW 或 PAGE(可混合),不能有任何 NONE。
  3. 支持的类型变更
    • 整数:smallint → int/bigint、int → bigint
    • 货币:smallmoney → money
    • 字符串/二进制:char(n) → char(m) 或 varchar(m)(n < m 且 m ≠ max),nchar/binary 同理
    • 不支持 :tinyint 任何扩宽、缩小类型、可空 → 非空
  4. 表类型:必须是 rowstore(非 columnstore)
  5. 不能同时修改可空性(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 有符号) 完整数据重写
可空 → 非空 任意 强制扫描数据,无法纯元数据 完整数据重写

五、推荐操作流程(想做秒级变更时)

  1. 用上面的查询确认压缩状态。
  2. 如果存在 NONE,先统一启用压缩(建议维护窗口执行):
sql 复制代码
-- 示例:整表重建为 PAGE 压缩(Enterprise/Developer 可用 ONLINE)
ALTER TABLE dbo.sample_table
REBUILD WITH (DATA_COMPRESSION = PAGE, ONLINE = ON);

或按索引逐个重建。

  1. 再次用查询确认全部为 ROW/PAGE。
  2. 执行类型变更:
sql 复制代码
ALTER TABLE dbo.sample_table
ALTER COLUMN 你的列名 bigint NOT NULL;   -- 或其他支持的扩宽

此时才会真正实现秒级元数据变更。


总结 :

能否「秒完成」栏位扩宽,核心取决于该表所有索引是否已全部启用 ROW/PAGE 压缩。未启用时先重建压缩的成本往往远高于直接改类型,需提前规划。

相关推荐
晴天¥2 小时前
记一次Oracle 归档进程卡死怎么去有效排查
数据库·oracle
小手cool2 小时前
PostgreSQL 基础入门:从安装到核心概念
数据库·postgresql
Bushlet2 小时前
Mysql建库及建表流程总结
数据库·mysql
梦幻通灵2 小时前
MybatisPlus使用数据库递增ID实现方案【持续更新】
数据库·oracle
l1t2 小时前
DeepSeek总结的从 SQL 桥梁到智能体基础设施:Hex 的 DuckDB 实践
数据库·sql·duckdb
代码派2 小时前
PostgreSQL 同构迁移上云方案|NineData 数据复制、实时增量与一致性校验
数据库·postgresql·上云·ninedata·迁移·数据库迁移·版本升级
孙琦Ray2 小时前
Speedb 数据引擎转向开源,RocksDB 替代方案迎来新竞争
数据库·开源·rocksdb·键值存储·speedb
与数据交流的路上2 小时前
一次 redis 幽灵内存的分析
数据库·redis·缓存