基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
GROUP BY
更新时间:2026-07-19 16:40:56
GROUP BY 算子主要用于在 SQL 中进行分组聚合计算操作。
GROUP BY 算子类型
OceanBase 数据库用于对数据进行分组的算法有 HASH 算法和 MERGE 算法,因此根据算法可以将 GROUP BY 算子分为两种:HASH GROUP BY 和 MERGE GROUP BY。执行计划生成时根据 SQL 优化器对于两种算子的代价评估,来选择使用哪种 GROUP BY 算子。
对于普通的聚合函数(SUM/MAX/MIN/AVG/COUNT/STDDEV)也是通过分配 GROUP BY 算子来完成,而对于只有聚合函数而不含有 GROUP BY 的 SQL,分配的是 SCALAR GROUP BY 算子,因此 GROUP BY 算子又可以分为三种:SCALAR GROUP BY、HASH GROUP BY 和 MERGE GROUP BY。
| 算子类型 | 特性说明 | 核心原理 | 适用场景 |
|---|---|---|---|
| SCALAR GROUP BY | 用于处理不含 GROUP BY 子句,但包含聚合函数(如 SUM, COUNT)的查询,对全表数据进行单一聚合。 |
对整张表的数据进行一次聚合计算,无需分组操作。 | 全局聚合统计,例如计算某列的总和、平均值、总行数等。 |
| HASH GROUP BY | 使用哈希表进行分组聚合,通常无需数据预先排序。 | 为每个不同的分组键计算一个哈希值,将相同哈希值的行放入同一桶中进行聚合计算。 | 分组键重复值较多或数据分布均匀时效率高,是常用的分组算法。 |
| MERGE GROUP BY | 使用排序合并算法进行分组聚合,要求输入数据已按分组键排序。 | 先确保数据按分组键有序(可能需额外 SORT 算子),然后顺序扫描已排序的数据流,合并相同键值的行进行聚合。 |
当数据已有序(如通过索引扫描获得),或需要保持输出有序时可能被优化器选用。 |
SCALAR GROUP BY
SCALAR GROUP BY 算子用于执行不含 GROUP BY 子句的标量聚合查询,即对整个结果集计算一个单一的聚合值。
SCALAR GROUP BY 示例
创建表
tbl1。obclient> CREATE TABLE tbl1 (col1 INT, col2 INT);Q1:对表
tbl1中col1列进行求和,同时查看该查询的执行计划。obclient> EXPLAIN SELECT SUM(col1) FROM tbl1;返回结果如下:
+-------------------------------------------------------------------------+ | Query Plan | +-------------------------------------------------------------------------+ | ================================================= | | |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| | | ------------------------------------------------- | | |0 |SCALAR GROUP BY | |1 |3 | | | |1 |└─TABLE FULL SCAN|TBL1|1 |3 | | | ================================================= | | Outputs & filters: | | ------------------------------------- | | 0 - output([T_FUN_SUM(T_FUN_SUM(TBL1.COL1))]), filter(nil), rowset=16 | | group(nil), agg_func([T_FUN_SUM(T_FUN_SUM(TBL1.COL1))]) | | 1 - output([T_FUN_SUM(TBL1.COL1)]), filter(nil), rowset=16 | | access([TBL1.COL1]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([TBL1.__pk_increment]), range(MIN ; MAX)always true, | | pushdown_aggregation([T_FUN_SUM(TBL1.COL1)]) | +-------------------------------------------------------------------------+ 15 rows in set
在 Q1 查询返回结果中,除了 SCALAR GROUP BY 算子(0 号算子),还展示了以下执行算子:
TABLE FULL SCAN:表示全表扫描。该算子属于TABLE SCAN算子,详细信息参见 TABLE SCAN。
上述 Q1 查询的执行计划展示中的 Outputs & filters 详细列出了 SCALAR GROUP BY 算子的输出信息如下:
| 信息名称 | 含义 | 示例说明 |
|---|---|---|
| output | 该算子最终输出的列或表达式列表。 | output([T_FUN_SUM(T_FUN_SUM(TBL1.COL1))]) 表示该算子输出的是表 tbl1 中 col1 列的总和。 |
| filter | 该算子需要应用的过滤条件(谓词)。 | filter(nil) 表示没有需要再额外过滤的行。 |
| rowset | 表示当前算子的向量化大小。 | rowset=16 表示当前算子的向量化大小为 16。 |
| group | 表示需要进行分组的列。 | SCALAR GROUP BY 算子用于不含 GROUP BY 子句的聚合查询,因此分组列为空,显示为 group(nil)。 |
| agg_func | 表示所涉及的聚合函数。 | Q1 查询是计算表 tbl1 的 col1 列数据之和,因此为 T_FUN_SUM(TBL1.COL1)。 |
HASH GROUP BY
HASH GROUP BY 算子用于执行使用哈希算法进行的分组聚合操作。
HASH GROUP BY 示例
创建表
tbl2。obclient> CREATE TABLE tbl2 (col1 INT, col2 INT);Q2:对表
tbl2按col1分组并计算每组col2的和,同时筛选出总和大于 2 的分组,查看该查询的执行计划。obclient> EXPLAIN SELECT SUM(col2) FROM tbl2 GROUP BY col1 HAVING SUM(col2) > 2;返回结果如下:
+-------------------------------------------------------------------------------------+ | Query Plan | +-------------------------------------------------------------------------------------+ | ================================================= | | |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| | | ------------------------------------------------- | | |0 |HASH GROUP BY | |1 |3 | | | |1 |└─TABLE FULL SCAN|TBL2|1 |3 | | | ================================================= | | Outputs & filters: | | ------------------------------------- | | 0 - output([T_FUN_SUM(TBL2.COL2)]), filter([T_FUN_SUM(TBL2.COL2) > 2]), rowset=16 | | group([TBL2.COL1]), agg_func([T_FUN_SUM(TBL2.COL2)]) | | 1 - output([TBL2.COL1], [TBL2.COL2]), filter(nil), rowset=16 | | access([TBL2.COL1], [TBL2.COL2]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([TBL2.__pk_increment]), range(MIN ; MAX)always true | +-------------------------------------------------------------------------------------+ 14 rows in set
在 Q2 查询返回结果中,除了 HASH GROUP BY 算子(0 号算子),还展示了以下执行算子:
TABLE FULL SCAN:表示全表扫描。该算子属于TABLE SCAN算子,详细信息参见 TABLE SCAN。
上述 Q2 查询的执行计划展示中的 Outputs & filters 详细列出了 HASH GROUP BY 算子的输出信息如下:
| 信息名称 | 含义 | 示例说明 |
|---|---|---|
| output | 该算子最终输出的列或表达式列表。 | output([T_FUN_SUM(TBL2.COL2)]) 表示该算子输出的是表 tbl2 中 col2 列的总和。 |
| filter | 该算子需要应用的过滤条件(谓词)。 | filter([T_FUN_SUM(TBL2.COL2) > 2]) 表示该算子上的过滤条件是分组后的列 col2 和大于 2。 |
| rowset | 表示当前算子的向量化大小。 | rowset=16 表示当前算子的向量化大小为 16。 |
| group | 表示需要进行分组的列。 | group([TBL2.COL1]) 表示对 tbl2 表的 col1 列进行分组。 |
| agg_func | 表示所涉及的聚合函数。 | Q2 查询是计算表 tbl2 的 col2 列数据之和,因此为 T_FUN_SUM(TBL2.COL2)。 |
说明
HASH GROUP BY 算子将会保证在执行时采用 HASH 算法进行分组。
MERGE GROUP BY
MERGE GROUP BY 算子用于执行使用排序合并算法进行的分组聚合操作。当优化器选择此算法时,它通常需要其输入数据已按分组键排序。
MERGE GROUP BY 示例
创建表
tbl3。obclient> CREATE TABLE tbl3 (col1 INT, col2 INT);Q3:使用 Hint 强制优化器使用
MERGE GROUP BY,对表tbl3按col1分组并计算每组col2的和,同时筛选出总和大于 2 的分组,查看该查询的执行计划。obclient> EXPLAIN SELECT /*+NO_USE_HASH_AGGREGATION*/ SUM(col2) FROM tbl3 GROUP BY col1 HAVING SUM(col2) > 2;返回结果如下:
+-------------------------------------------------------------------------------------+ | Query Plan | +-------------------------------------------------------------------------------------+ | =================================================== | | |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| | | --------------------------------------------------- | | |0 |MERGE GROUP BY | |1 |3 | | | |1 |└─PARTITION SORT | |1 |3 | | | |2 | └─TABLE FULL SCAN|TBL3|1 |3 | | | =================================================== | | Outputs & filters: | | ------------------------------------- | | 0 - output([T_FUN_SUM(TBL3.COL2)]), filter([T_FUN_SUM(TBL3.COL2) > 2]), rowset=16 | | group([TBL3.COL1]), agg_func([T_FUN_SUM(TBL3.COL2)]) | | 1 - output([TBL3.COL1], [TBL3.COL2]), filter(nil), rowset=16 | | sort_keys([HASH(TBL3.COL1), ASC], [TBL3.COL1, ASC]) | | 2 - output([TBL3.COL1], [TBL3.COL2]), filter(nil), rowset=16 | | access([TBL3.COL1], [TBL3.COL2]), partitions(p0) | | is_index_back=false, is_global_index=false, | | range_key([TBL3.__pk_increment]), range(MIN ; MAX)always true | +-------------------------------------------------------------------------------------+ 17 rows in set
上述示例中,Q3 查询的执行计划展示中的 Outputs & filters 中详细列出了 MERGE GROUP BY 算子的信息,与 HASH GROUP BY 算子相比,其 output、filter、group、agg_func 等信息的含义是相同的。最大的区别在于执行时选择的分组算法不一样,且由于 MERGE GROUP BY 需要输入数据有序,而 TABLE FULL SCAN 返回的是无序结果,因此优化器在 MERGE GROUP BY 算子之下分配了一个 PARTITION SORT(或 SORT)算子来对数据进行排序。
PARTITION SORT:表示分区排序。该算子属于 SORT 算子,详细信息参见 SORT。
注意
NO_USE_HASH_AGGREGATION 和 USE_HASH_AGGREGATION 的 Hint 可以用于控制 GROUP BY 算子选择何种算法进行分组。