更新时间:2025-05-29 GMT+08:00

分布式计划

目前,GaussDB优化器在分布式框架下制定语句的执行策略时,有三种执行计划方式:生成下推语句计划、生成分布式执行计划、生成发送语句的分布式执行计划。

  • 下推语句计划:指直接将查询语句从CN发送到DN进行执行,然后将执行结果返回给CN。
  • 分布式执行计划:指CN对查询语句进行编译和优化,生成计划树,再将计划树发送给DN进行执行,并在执行完毕后返回结果到CN。
  • 发送语句的分布式执行计划:上述两种方式都不可行时,将可下推的查询部分组成查询语句(多为基表扫描语句)下推到DN进行执行,获取中间结果到CN,然后在CN执行剩下的部分。

下推语句计划:

gaussdb=# CREATE TABLE t1(c1 int,c2 int);
gaussdb=# CREATE TABLE t2(c1 int,c2 int);
gaussdb=# EXPLAIN SELECT * FROM t1;
                    QUERY PLAN
--------------------------------------------------
 Data Node Scan  (cost=0.00..0.00 rows=0 width=0)
   Node/s: All datanodes
(2 rows)

计划字段解读:

  • Data Node Scan

    代表SQL语句被下推到DN上进行计划生成和执行。

  • Node/s: All datanodes

    表示SQL语句会在所有DN上执行。

使用EXPLAIN VERBOSE看到下发的SQL语句:

gaussdb=# EXPLAIN VERBOSE SELECT * FROM t1;
                    QUERY PLAN
--------------------------------------------------
 Data Node Scan  (cost=0.00..0.00 rows=0 width=0)
   Output: t1.c1, t1.c2
   Node/s: All datanodes
   Remote query: SELECT c1, c2 FROM public.t1
(4 rows)

可以看到执行计划中多了Remote query字段,该字段描述了下发的SQL语句。如果想更进一步查看SQL下推到DN上后的计划可以设置参数max_datanode_for_plan,该参数表示显示DN上计划的个数,显示DN上计划的个数由集群中的DN数和该参数值的更小者决定。

gaussdb=# SET max_datanode_for_plan = 1;
gaussdb=# EXPLAIN VERBOSE SELECT * FROM t1;
                        QUERY PLAN
-----------------------------------------------------------
 Data Node Scan  (cost=0.00..0.00 rows=0 width=0)
   Output: t1.c1, t1.c2
   Node/s: All datanodes
   Remote query: SELECT c1, c2 FROM public.t1

 Remote SQL: SELECT c1, c2 FROM public.t1
 Datanode Name: datanode1
   Seq Scan on public.t1  (cost=0.00..1.06 rows=6 width=8)
     Output: c1, c2

(10 rows)

此时可以看到datanode1上的计划。

分布式执行计划:

当SQL语句不能下推时,会优先生成分布式执行计划:

gaussdb=# SET query_mem = '256MB';
SET
gaussdb=# EXPLAIN SELECT * FROM t1 JOIN t2 ON t1.c1 = t1.c2;
 id |              operation               | E-rows | E-memory | E-width | E-costs
----+--------------------------------------+--------+----------+---------+---------
  1 | ->  Streaming (type: GATHER)         |     10 |          |      16 | 2.79
  2 |    ->  Nested Loop (3,5)             |     10 | 1MB      |      16 | 2.32
  3 |       ->  Streaming(type: BROADCAST) |      2 | 2MB      |       8 | 1.22
  4 |          ->  Seq Scan on t1          |      1 | 1MB      |       8 | 1.06
  5 |       ->  Seq Scan on t2             |     10 | 1MB      |       8 | 1.05
(5 rows)

 Predicate Information (identified by plan id)
-----------------------------------------------
   4 --Seq Scan on t1
         Filter: (c1 = c2)
(2 rows)

   ====== Query Summary =====
---------------------------------
 System available mem: 8193638KB
 Query Max mem: 8280473KB
 Query estimated mem: 5152KB
(3 rows)

其中,当query_mem参数为0时,QUERY SUMMARY的内容则不会显示。

分布式执行计划有一个特殊的Streaming算子,其实现了分布式架构的核心数据shuffle功能,Streaming共有三种形态,分别对应了分布式结构下不同的数据shuffle功能:
  • Streaming(type: GATHER):作用是coordinator从DN收集数据。
  • Streaming(type: REDISTRIBUTE):作用是DN根据选定的列把数据重分布到所有的DN
  • Streaming(type: BROADCAST):作用是把当前DN的数据广播给其他所有的DN

发送语句的分布式执行计划

当前两种执行计划都不能生成时,会生成发送语句的执行计划:

gaussdb=# ANALYZE t1;
ANALYZE
gaussdb=# EXPLAIN SELECT * FROM t1 limit 1;
                                     QUERY PLAN
-------------------------------------------------------------------------------------
 Limit  (cost=0.00..0.00 rows=1 width=15)
   ->  Data Node Scan on "__REMOTE_LIMIT_QUERY__"  (cost=0.00..0.00 rows=1 width=15)
         Node/s: All datanodes
(3 rows)


--删除表。
gaussdb=# DROP TABLE t1,t2;

带有LIMIT的语句,对于CN而言不能简单发语句给DN并收集数据,明显与LIMIT语义不符。可以看到执行计划将LIMIT 1语句分发到所有DN上,然后在将中间结果收集到CN后,在CN做最后的LIMIT处理。