GROUP BY 实施选项
Vertica 将使用以下算法之一来实施查询 GROUP BY 子句:GROUPBY PIPELINED 或 GROUPBY HASH。这两种算法会返回相同的结果。对于返回少量不同组(通常每个节点一千个)的查询,两者的性能基本相似。
您可以使用 EXPLAIN 来确定查询优化器为给定查询选择的算法。以下条件通常决定选择哪种算法:
-
GROUPBY PIPELINED 要求在投影的 ORDER BY 子句中指定所有 GROUP BY 数据。有关详细信息,请参阅下面的 GROUPBY PIPELINED 要求。
由于 GROUPBY PIPELINED 只需在内存中保留当前组数据,因此相比 GROUPBY HASH,该算法通常需要的内存更少且执行速度更快。对于聚合大量不同组的查询,性能改进尤为显著。
-
GROUPBY HASH 将用于任何不符合 GROUPBY PIPELINED 排序顺序要求的查询。在这种情况下,Vertica 必须先对各个 GROUP BY 列构建哈希表,然后才能开始对数据进行分组。
GROUPBY PIPELINED 要求
通过确保查询及其投影之一符合 GROUPBY PIPELINED 要求,可以启用 GROUPBY PIPELINED 算法。以下条件适用于 GROUPBY PIPELINED。如果查询不满足任何条件,则 Vertica 使用 GROUPBY HASH。
后续所有示例均假定使用此架构:
CREATE TABLE sortopt (
a INT NOT NULL,
b INT NOT NULL,
c INT,
d INT
);
CREATE PROJECTION sortopt_p (
a_proj,
b_proj,
c_proj,
d_proj )
AS SELECT * FROM sortopt
ORDER BY a,b,c
UNSEGMENTED ALL NODES;
INSERT INTO sortopt VALUES(5,2,13,84);
INSERT INTO sortopt VALUES(14,22,8,115);
INSERT INTO sortopt VALUES(79,9,401,33);
条件 1
所有 GROUP BY 列也包含在投影 ORDER BY 子句中。例如:
条件 2
如果查询的 GROUP BY 子句比投影的 ORDER BY 子句拥有的列数少,则 GROUP BY 列必须:
-
是连续的 ORDER BY 列的子集。
-
包含第一个 ORDER BY 列。
例如:
条件 3
如果查询的 GROUP BY 列不是先出现在投影的 GROUP BY 子句中,则在查询的 GROUP BY 子句中缺失的任何先出现的投影排序列必须在查询的 WHERE 子句中显示为单列恒定相等谓词。
例如:
控制选择的 GROUPBY 算法
通常最好让 Vertica 来确定最适合用于给定查询的 GROUP BY 算法。有时,您可能希望使用某种算法,而不是另一种算法。在这种情况下,您可以使用 GBYTYPE 提示来限定 GROUP BY 子句:
GROUP BY /*+ GBYTYPE( HASH | PIPE ) */
例如,指定以下查询后,查询优化器将使用 GROUPBY PIPELINED 算法:
=> EXPLAIN SELECT SUM(a) FROM sortopt GROUP BY a,b;
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------
EXPLAIN SELECT SUM(a) FROM sortopt GROUP BY a,b;
Access Path:
+-GROUPBY PIPELINED [Cost: 11, Rows: 3 (NO STATISTICS)] (PATH ID: 1)
| Aggregates: sum(sortopt.a)
| Group By: sortopt.a, sortopt.b
...
您可以使用 GBYTYPE 提示来强制查询优化器使用 GROUPBY HASH 算法:
=> EXPLAIN SELECT SUM(a) FROM sortopt GROUP BY /*+GBYTYPE(HASH) */ a,b;
------------------------------
QUERY PLAN DESCRIPTION:
------------------------------
EXPLAIN SELECT SUM(a) FROM sortopt GROUP BY /*+GBYTYPE(HASH) */ a,b;
Access Path:
+-GROUPBY HASH (LOCAL RESEGMENT GROUPS) [Cost: 11, Rows: 3 (NO STATISTICS)] (PATH ID: 1)
| Aggregates: sum(sortopt.a)
| Group By: sortopt.a, sortopt.b
...
仅当查询及其投影之一符合 GROUPBY PIPELINED 要求时,GBYTYPE 提示才能指定 PIPE(GROUPBY PIPELINED 算法)实参。否则,Vertica 会发出警告并使用 GROUPBY HASH。
例如,以下查询不能使用 GROUPBY PIPELINED 算法,因为 GROUP BY 列 {b,c
} 不包含投影的第一个 ORDER BY 列 a
:
=> SELECT SUM(a) FROM sortopt GROUP BY /*+GBYTYPE(PIPE) */ b,c;
WARNING 7765: Cannot apply Group By Pipe algorithm. Proceeding with Group By Hash and hint will be ignored
SUM
-----
79
14
5
(3 rows)