
# 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;
```
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
Partition-wise Join计划的执行性能取决于数据量最大的分区的执行性能。所以在分区间存在严重的数据倾斜或存在分区剪枝的场景下，Partition-wise Join可能导致性能劣化。
