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)