文档首页/ 云数据库 GaussDB/ 开发指南(分布式_V2.0-10.x)/ 特性使用指导/ 分区表/ 分区表查询优化/ Partition-wise Join/ SMP场景下的Partial Partition-wise Join
更新时间: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可能导致性能劣化。
父主题: Partition-wise Join