更新时间:2024-11-12 GMT+08:00
分享

SMP场景下的Full Partition-wise Join

SMP场景下的Partition-wise Join计划是基于代价选择的,在路径生成的过程中,会对比Partition-wise Join和非Partition-wise Join路径的估算代价,选择代价较低的路径。其开关参数为GUC参数enable_smp_partitionwise。

Full Partition-wise Join是指相互Join的两张表为分区策略完全相同的两张分区表,Full Partition-wise Join路径生成条件是两张表的分区键是一对相互匹配的Join key。

使用规格

SMP场景下的Full Partition-wise Join的使用规格:

  • 支持一级HASH分区表和一级RANGE分区表。
  • Hash分区表的分区策略完全相同是指分区键类型相同、分区数相同。
  • Range分区表的分区策略完全相同是指分区键类型相同、分区数相同、分区键数量相同、每个分区的边界值相同。
  • 仅支持Stream计划。
  • 仅支持分区键和分布键完全一致的场景。
  • 仅支持Join算子在单DN内完成计算,即Join算子的数据不跨节点。
  • 支持Hash Join和Merge Join。
  • 支持Seqscan、Indexscan、Indexonlyscan、Imcvscan。其中,对于Indexscan和Indexonlyscan,只支持分区Local索引,且索引类型为BTREE或UBTREE。
  • 相关规格继承SMP规格,不支持SMP场景下的IUD操作。
  • 需要开启SMP功能,且设置query_dop的值大于1。

示例

--创建Hash分区表。
gaussdb=# CREATE TABLE hash_part
(
    a INTEGER,
    b INTEGER,
    c INTEGER
)
DISTRIBUTE BY HASH(a)
PARTITION BY HASH(a)
(
    PARTITION p1,
    PARTITION p2,
    PARTITION p3,
    PARTITION p4,
    PARTITION p5
);
CREATE TABLE

--使用Stream计划。
gaussdb=# SET enable_fast_query_shipping = off;
SET
gaussdb=# SET enable_stream_operator = on;
SET

--设置query_dop为5,开启SMP。
gaussdb=# SET query_dop = 5;
SET

--关闭SMP场景下的Partition-wise Join开关。
gaussdb=# SET enable_smp_partitionwise = off;
SET

--查看非Partition-wise Join的计划。从计划中可以看出来,在通过Partition Iterator+Partitioned Seq Scan两层算子完成数据扫描之后,通过Streaming(type: LOCAL REDISTRIBUTE)算子对数据进行了一次重分布,用于保证Join算子中数据能够相互匹配。
gaussdb=# EXPLAIN (COSTS OFF) SELECT * FROM hash_part t1, hash_part t2 WHERE t1.a = t2.a;
                                QUERY PLAN                                
--------------------------------------------------------------------------
 Streaming (type: GATHER)
   Node/s: All datanodes
   ->  Streaming(type: LOCAL GATHER dop: 1/5)
         Spawn on: All datanodes
         ->  Nested Loop
               Join Filter: (t1.a = t2.a)
               ->  Streaming(type: LOCAL REDISTRIBUTE dop: 5/5)
                     Spawn on: All datanodes
                     ->  Partition Iterator
                           Iterations: 5
                           ->  Partitioned Seq Scan on hash_part t1
                                 Selected Partitions:  1..5
               ->  Materialize
                     ->  Streaming(type: LOCAL REDISTRIBUTE dop: 5/5)
                           Spawn on: All datanodes
                           ->  Partition Iterator
                                 Iterations: 5
                                 ->  Partitioned Seq Scan on hash_part t2
                                       Selected Partitions:  1..5
(19 rows)

--打开SMP场景下的Partition-wise Join开关。
gaussdb=# SET enable_smp_partitionwise = on;
SET

--查看Partition-wise Join的执行计划。从计划中可以看出,Partition-wise Join计划消除掉了Streaming算子,即数据不再需要在线程之间重新分布,减少了数据搬运的开销,提升了Join操作的性能。
gaussdb=# EXPLAIN (COSTS OFF) SELECT * FROM hash_part t1, hash_part t2 WHERE t1.a = t2.a;
                             QUERY PLAN                             
--------------------------------------------------------------------
 Streaming (type: GATHER)
   Node/s: All datanodes
   ->  Streaming(type: LOCAL GATHER dop: 1/5)
         Spawn on: All datanodes
         ->  Hash Join (Partition-wise Join)
               Hash Cond: (t1.a = t2.a)
               ->  Partition Iterator
                     Iterations: 5
                     ->  Partitioned Seq Scan on hash_part t1
                           Selected Partitions:  1..5
               ->  Hash
                     ->  Partition Iterator
                           Iterations: 5
                           ->  Partitioned Seq Scan on hash_part t2
                                 Selected Partitions:  1..5
(15 rows)

-- 删除分区表
gaussdb=# DROP TABLE hash_part;

仅在SMP场景下的Partition-wise Join计划中,Join算子右侧会有(Partition-wise Join)提示信息。非SMP场景无该提示信息。

相关文档