更新时间:2026-07-28 GMT+08:00
分享

SMP场景下的Partial Partition-wise Join

Partial Partition-wise Join是指相互Join的两张表中有一张表是分区表,另一张表可以为任意类型,在任意类型的这张表的上层需要增加一个Stream Redistribute算子,将数据分发后与分区表一侧进行匹配。Partial Partition-wise Join路径生成的条件是分区表的分区键是一个Join key。

使用规格

继承SMP场景下的Full Partition-wise Join的使用规格。

约束

  • 不支持对range分布的中间结果表的Partial Partition-wise Join。
  • 其他约束继承SMP场景下的Full Partition-wise Join的约束。

示例

非透明多写特性下:

--创建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

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

--不走nest loop计划。
gaussdb=# SET enable_material=off;
SET
gaussdb=# SET enable_broadcast=off;
SET
gaussdb=# SET enable_nestloop=off;
SET

-- 插入10万条基础测试数据(a/b/c为随机整数,保证哈希分布的随机性)。
gaussdb=# INSERT INTO hash_part (a, b, c) 
SELECT 
  FLOOR(RANDOM() * 1000000)::INTEGER AS a,
  FLOOR(RANDOM() * 500000)::INTEGER AS b,
  FLOOR(RANDOM() * 1000)::INTEGER AS c
FROM GENERATE_SERIES(1, 100000);
INSERT 0 100000

-- 循环5次,每次将现有数据翻倍插入(最终总数据量 = 10万 * 2^5 = 320万)。
gaussdb=# DO $$
BEGIN
  FOR i IN 1..5 LOOP
    INSERT INTO hash_part (a, b, c) 
    SELECT a, b, c FROM hash_part;
  END LOOP;
END 
$$;
ANONYMOUS BLOCK EXECUTE

--analyze数据。
gaussdb=# ANALYZE;
ANALYZE

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

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

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

--查看Partition-wise Join的执行计划。从计划中可以看出,Partial Partition-wise Join计划消除掉了分布表hash_part一侧的Streaming算子,即分区表的数据不再需要在线程之间重新分布,减少了数据搬运的开销,提升了Join操作的性能。
gaussdb=# EXPLAIN (costs off) SELECT * FROM hash_part t1, hash_part t2 WHERE t1.a=t2.b;
                             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: (t2.b = t1.a)
               ->  Streaming(type: SPLIT REDISTRIBUTE dop: 5/5)
                     Spawn on: All datanodes
                     ->  Partition Iterator
                           Iterations: 5
                           ->  Partitioned Seq Scan on hash_part t2
                                 Selected Partitions:  1..5
               ->  Hash
                     ->  Partition Iterator
                           Iterations: 5
                           ->  Partitioned Seq Scan on hash_part t1
                                 Selected Partitions:  1..5
(17 rows)

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

Partition-wise Join计划的执行性能取决于数据量最大的分区的执行性能。所以在分区间存在严重的数据倾斜或存在分区剪枝的场景下,Partition-wise Join可能导致性能劣化。

相关文档