能触发批模式的分组查询需满足:扫描对象含列存储索引且group by/聚合列在其内,或启用trace flag 11179配合行存储表与更新统计信息,且无阻塞算子、无不支持数据类型或函数;order by会禁用批模式,除非顺序天然满足;验证须看执行计划中batch hash aggregate运算符及estimated/actualexecutionmode均为batch。

SQL Server 2022 默认支持批处理模式执行分组查询,但前提是底层数据结构或查询条件满足启用条件——不是所有 GROUP BY 查询都会自动走批模式,盲目加索引或改写反而可能绕过它。
哪些分组查询能触发批模式?
批模式执行对分组聚合的加速依赖硬件感知和数据组织方式。以下情况会实际启用批模式:
- 查询扫描对象包含列存储索引(哪怕只是非聚集列存储索引),且
GROUP BY列和聚合列都在该索引中 - 启用了
trace flag 11179(SQL Server 2022+)并配合行存储表 + 全局统计信息更新,部分简单分组可降级启用批模式 - 使用
SELECT ... GROUP BY且无阻塞算子(如排序、哈希匹配前的显式ORDER BY),同时目标列未被TEXT/XML/MAX类型污染 - 在 Azure SQL 数据库或 SQL Server 2022 中,若查询计划里出现
Batch Hash Aggregate或Batch Sort运算符,说明已进入批模式
GROUP BY 后加 ORDER BY 会禁用批模式吗?
会。只要 ORDER BY 的表达式不能由列存储段内天然顺序满足,SQL Server 就必须插入一个 Sort 运算符——而传统 Sort 是行模式算子,会打断批模式流水线。
实操建议:
- 如果业务只要求“每组一个结果”,去掉
ORDER BY,让聚合结果保持自然输出顺序 - 若必须排序,优先把排序字段加入
PARTITION BY或利用OVER ()窗口函数延迟排序,例如:MAX(value) OVER (PARTITION BY category ORDER BY ts ROWS UNBOUNDED PRECEDING) - 检查执行计划:若看到
Sort前有Row Mode标记,说明批模式已被中断
为什么加了列存储索引还是没走批模式?
常见原因不是索引没建好,而是查询本身“污染”了批模式路径:
- SELECT 列中混入了不支持批处理的数据类型,比如
geography、hierarchyid、sql_variant或未压缩的varchar(max) - WHERE 条件用了不支持批模式的函数,如
DATEADD(day, 1, col)或自定义 CLR 函数 - 连接了堆表或 B-tree 行存储表,且优化器判定混合访问代价高于纯批模式收益
- 服务器配置了
trace flag 834(大页内存)——这与批模式存在已知互斥问题,会导致非生成计划程序错误甚至崩溃(KB 3210239)
如何验证当前查询是否真正在批模式下分组?
别只看“列存储索引存在”,要盯执行计划里的具体运算符行为:
- 打开实际执行计划(
SET STATISTICS XML ON),搜索Batch Hash Aggregate;如果是Hash Aggregate(无 Batch 前缀),就是行模式 - 右键运算符 → 属性 → 查看
EstimatedExecutionMode和ActualExecutionMode,二者都应为Batch - 对比逻辑读和 CPU 时间:批模式分组通常
logical reads更低、cpu_time占总耗时比更高(因大量向量化计算压在 CPU) - 注意警告:计划里若有
Warning: No Join Predicate或Convert Insert,也可能间接压制批模式选择
批模式分组真正的门槛不在语法,而在数据布局与查询干净度。一个 CONVERT(varchar, dt) 就可能让整个聚合退回到行模式——这种细节在执行计划里不放大看根本发现不了。










