stream aggregate效率更高仅当输入数据已按group by字段天然有序且无需额外排序,此时它边读边聚、内存恒定、时间复杂度o(n);若输入无序则需前置sort,实际开销在排序而非流聚本身。

流聚合(Stream Aggregate)比哈希聚合(Hash Aggregate)效率更高,仅当输入数据已按 GROUP BY 字段天然有序,且无需额外排序时成立。 它不是“算法更优”,而是直接跳过了哈希表构建和随机内存访问这两个开销大户。
Stream Aggregate 为什么快?关键看输入是否有序
Stream Aggregate 的核心是“边读边聚”:它假设输入行已按 GROUP BY 字段升序排列,只需维护一个当前分组的累加器,遇到键变化就输出上一组结果。整个过程内存恒定(通常几 KB),无哈希桶、无扩容、不 spill。
而 Hash Aggregate 必须:先读完全部输入,为每个分组键计算哈希值并存入内存哈希表;再遍历哈希表输出结果。哪怕只想要前 10 行,也得等全量建表完成。
- 输入有序时,
Stream Aggregate时间复杂度是 O(N),空间是 O(1) - 输入无序时,优化器会悄悄在它前面插一个
Sort节点——这时真正耗时的是排序,不是 Stream Aggregate 本身 - 若输入来自索引扫描(如
Index Scan或Clustered Index Seek),且执行计划中该节点属性含Ordered="true",才说明真免了排序
怎么确认你用的真是 Stream Aggregate 而不是“假流真排”?
不能只看执行计划顶部写着 Stream Aggregate 就放心。必须下钻验证其直接上游节点:
- 上游必须是
Index Scan、Index Only Scan或Clustered Index Seek,不能是Sort或Seq Scan - 上游节点 XML 属性中必须有
Ordered="true"(SQL Server 查RelOp节点;PostgreSQL 用EXPLAIN (ANALYZE)看Ordering字段) - 对比
EstimatedRows和ActualRows:偏差超 5 倍,说明统计信息过期,UPDATE STATISTICS或ANALYZE后重试
哪些写法会让 Stream Aggregate 失效?
哪怕索引建得再准,以下操作都会破坏有序性,迫使优化器插入 Sort:
- 在
GROUP BY中做计算:GROUP BY UPPER(name)、GROUP BY ISNULL(id, 0) - 隐式类型转换:
GROUP BY user_id(INT)但字段实际是VARCHAR,触发转换后索引失效 - 未命中索引最左前缀:有复合索引
INDEX (status, created_at),却写GROUP BY created_at - 带
LIMIT/TOP/OFFSET:部分优化器认为“有序流不可靠”,主动降级为Hash Aggregate
什么时候坚持用 Stream Aggregate 反而更慢?
Stream Aggregate 的优势只在特定条件下兑现:
- 输入行数大(百万级以上)且天然有序(如日志表按
event_time聚簇、订单表主键自增) - 查询需早期终止(如嵌套在
CROSS APPLY中,或外层有LIMIT 100) - 内存紧张——
Hash Aggregate可能申请几百 MB,Stream Aggregate只要几 KB
反例很常见:小表聚合(几千行)、或聚合后还要 JOIN 其他表但统计信息不准,此时 Hash Aggregate 构建小哈希表反而更快。真正卡住性能的,从来不是算子名字,而是优化器看到的“数据顺序是否真实可信”。漏掉索引定义、字段类型、查询写法、统计信息中任意一环,Stream Aggregate 就会从省资源变成背锅侠。










