SQL Server 2019中GROUP BY走批处理模式必须同时满足四个条件:兼容级别≥150、基表含聚集列存储索引、聚合表达式无禁用操作、无强制降级提示;任一缺失则Actual Execution Mode=Row。

SQL Server 2019 中 GROUP BY 能否走批处理模式,不取决于你写了什么聚合函数,而取决于数据是否从列存储索引流进来、执行计划是否真正启用批模式——其他所有优化都是徒劳的。
必须同时满足的四个硬性条件
缺一不可,哪怕只漏一个,执行计划里就只会看到 Actual Execution Mode = Row:
-
ALTER DATABASE [db_name] SET COMPATIBILITY_LEVEL = 150或更高(不能是 140) - 基表必须建有
CLUSTERED COLUMNSTORE INDEX;堆表、CLUSTERED INDEX、NONCLUSTERED INDEX全部无效 - 聚合表达式中不能出现禁用批处理的操作:比如
CAST(price AS DECIMAL(18,4))、GETDATE()、STRING_AGG()、对VARCHAR(MAX)列做SUM或COUNT - 不能在查询中使用
OPTION (USE HINT('DISALLOW_BATCH_MODE'))或其它强制降级提示
为什么加了 HAVING 或 ORDER BY 就退化成行模式?
它们本身不直接禁用批处理,但常触发隐式路径断裂:
-
HAVING COUNT(*) > 10是安全的;但如果前面WHERE status = N'shipped'引入了 Unicode 隐式转换,扫描阶段就会退化为行模式,上游断了,下游聚合自然也走不了批模式 -
ORDER BY region若与GROUP BY region字段一致,且列存储索引键顺序匹配,可能跳过排序;但一旦写成ORDER BY SUM(amount) DESC,就会插入一个Sort运算符,彻底阻断批流 - 任何聚合后计算,如
SELECT region, SUM(sales) * 1.05,都可能被Compute Scalar拦截,导致后续无法继续批处理
如何确认批处理真的生效了?
别信“看起来快了”,只看执行计划里的两个关键信号:
- 聚合运算符(如
Hash Match Aggregate)属性中必须同时存在:Actual Execution Mode = Batch和BatchModeOnRowstore = true(后者仅在行存上启用批处理时出现;列存场景下不显示该属性,但Actual Execution Mode = Batch必须存在) - 上游扫描/连接算子也必须是
Batch模式;如果扫描是Row,聚合再标Batch也是假象(SQL Server 2019 不支持跨模式接力) - 不要依赖
SET STATISTICS XML ON后肉眼扫 plan —— 一定要右键“属性”,逐个点开算子看Actual Execution Mode字段值
最容易被忽略的是:即使你建了列存储索引,如果表上有频繁的 INSERT/UPDATE/DELETE,而你又没定期运行 ALTER INDEX ... REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON),大量 delta store 未压缩,扫描仍会回退到行模式。批处理不是“建完索引就自动永久开启”的功能,它对数据物理布局非常敏感。










