sql server不存在“列存聚合索引”,正确选择是聚集列存储索引(clustered columnstore index),它适用于只读历史归档表,提供高压缩率和批处理模式下的聚合查询加速,但要求表无不支持的数据类型、稀疏列、计算列等限制。

不能直接为历史归档数据建立“列存聚合索引”——SQL Server 没有这个索引类型,你真正需要的是聚集列存储索引(CLUSTERED COLUMNSTORE INDEX),且它天然适合只读/低频更新的历史归档场景。
为什么不能用 CREATE AGGREGATE INDEX?
SQL Server 从不提供名为 “aggregate index” 或 “aggregation index” 的索引语法。所有官方文档、语法手册、系统视图中均无 AGGREGATE 关键字出现在 CREATE INDEX 语句中。常见混淆来源是误将“列存储索引支持批处理模式下的聚合运算(如 SUM/COUNT)”理解为存在一种专用于聚合的索引类型。
- 实际能用的只有:
CLUSTERED COLUMNSTORE和NONCLUSTERED COLUMNSTORE - 所谓“聚合加速”,是列存储引擎在执行
GROUP BY、SUM等操作时,利用数据段(rowgroup)压缩 + 批处理(batch mode)自动优化的结果,不是靠索引定义里写个“aggregate”实现的 - 试图执行类似
CREATE AGGREGATE INDEX ...会直接报错:Incorrect syntax near 'AGGREGATE'
历史归档表该用 CLUSTERED COLUMNSTORE 还是 NONCLUSTERED COLUMNSTORE?
优先选 CLUSTERED COLUMNSTORE INDEX,前提是这张表已完全转入只读归档状态(后续不再 INSERT/UPDATE/DELETE)。
-
CLUSTERED COLUMNSTORE会重写整个表的物理存储结构,把行式数据彻底转为按列压缩的格式,节省空间(通常 7x+ 压缩率),并启用批处理执行模式——这对SUM/AVG/COUNT/DISTINCT类聚合查询提升最明显 - 如果表仍需偶尔更新(比如补录少量记录),必须用
NONCLUSTERED COLUMNSTORE,但注意:它会在原堆或聚集索引之上额外增加一份列存副本,占用双份存储空间 - SQL Server 2014+ 支持
CLUSTERED COLUMNSTORE上的INSERT,但性能开销大;2016+ 引入了DELTA STORE机制缓解,但归档表没必要承担这个复杂度
建索引前必须清理的 4 个硬性限制
列存储索引对数据类型和表结构敏感,踩中任意一条都会导致 CREATE INDEX 失败:
- 表中不能含
varchar(max)、nvarchar(max)、xml、text、image、sql_variant、geography、geometry等不支持列存的类型(可用SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('YourTable') AND system_type_id IN (231,239,241,34,35,98,99,100,101,102,103,104,105,106,107,108,109,110,111,122,127,165,167,173,175,189,231,241)快速筛查) - 不能有稀疏列(
SPARSE)、计算列(PERSISTED也不行)、FILESTREAM列 - 不能已有聚集索引(
CLUSTERED COLUMNSTORE本身就是聚集索引,二者互斥);若原表有主键聚集索引,需先DROP主键约束或用DROP_EXISTING = ON覆盖 - 表所有权必须明确:不能跨数据库引用,且不能是临时表、表变量、内存优化表
一条安全建索引的典型命令
假设归档表 ArchiveSales_2020_2023 已确认无上述受限列,且无任何索引:
CREATE CLUSTERED COLUMNSTORE INDEX IX_ArchiveSales_CCI ON ArchiveSales_2020_2023 WITH (DROP_EXISTING = OFF, MAXDOP = 4);
关键点说明:
-
DROP_EXISTING = OFF:确保不会误删其他非列存索引(虽然归档表通常没有) -
MAXDOP = 4:限制并行度,避免建索引过程吃光服务器资源;生产环境建议设为 CPU 核数的 75%(如 16 核设为 12) - 不要加
WHERE过滤子句:列存储索引不支持过滤索引(FILTERED INDEX),想分区归档请用表分区(partition scheme)而非索引过滤 - 建完立刻执行
DBCC SHRINKFILE无意义——列存数据本身已高度压缩,收缩日志或数据文件需单独评估
最易被忽略的是数据类型兼容性检查。很多人在 CREATE COLUMNSTORE INDEX 报错后反复调参数,却没意识到问题出在某列是 varchar(max) ——这种类型无法进入列存,必须提前用 ALTER TABLE ... ALTER COLUMN 改为定长 varchar(8000) 或拆到关联表中。










