更新时间:2026-07-28 GMT+08:00
hashbucket剪枝
在使用hashbucket表的时候,当select语句中谓词列和hashbucket表分布列相同时,会对hashbucket表进行剪枝操作,大幅缩减访问的bucket的数量。示例如下:
--准备环境。 gaussdb=# SET enable_fast_query_shipping=off; gaussdb=# CREATE TABLE t1 (a int, b int, c int) WITH (hashbucket=on, storage_type=astore); gaussdb=# INSERT INTO t1 VALUES(generate_series(1, 10), generate_series(1, 10)); gaussdb=# ANALYZE t1; --展示执行计划。 gaussdb=# EXPLAIN (costs false,verbose on) SELECT count(*) FROM t1 WHERE a = 1; QUERY PLAN ------------------------------------------------------- Aggregate Output: pg_catalog.count(*) -> Streaming (type: GATHER) Output: (count(*)) Node/s: datanode1 -> Aggregate Output: count(*) -> Seq Scan on public.t1 Output: a, b, c Distribute Key: a Filter: (t1.a = 1) Selected Buckets 1 of 1024 : 325 (12 rows)
可以看到计划中显示选择了325这个编号的bucket,则在实际执行的时候会直接读取这个bucket的数据,减少无意义的读取。
关于hashbucket的计划需要打开explain verbose才能显示。
hashbucket参数化路径剪枝
当选择参数化路径计划且hashbucket表作为内表时,若参数化的列是hashbucket表的分布列,会进行参数化路径的剪枝,动态削减访问bucket的数量。
--准备环境。 gaussdb=# SET enable_fast_query_shipping=off; gaussdb=# CREATE TABLE t2 (a int, b int, c int) WITH (hashbucket=on, storage_type=astore); gaussdb=# INSERT INTO t2 VALUES(generate_series(1, 10), generate_series(1, 10)); gaussdb=# CREATE INDEX index_t2 on t2(a, b); gaussdb=# ANALYZE t2; --展示执行计划。 gaussdb=# EXPLAIN (costs false,verbose on) SELECT /*+ nestloop_index(t2, index_t2)*/* FROM t1 JOIN t2 ON t1.b = t2.a; QUERY PLAN ----------------------------------------------------------------- Streaming (type: GATHER) Output: t1.a, t1.b, t1.c, t2.a, t2.b, t2.c Node/s: All datanodes -> Nested Loop Output: t1.a, t1.b, t1.c, t2.a, t2.b, t2.c -> Streaming(type: REDISTRIBUTE) Output: t1.a, t1.b, t1.c Distribute Key: t1.b Spawn on: All datanodes Consumer Nodes: All datanodes -> Seq Scan on public.t1 Output: t1.a, t1.b, t1.c Distribute Key: t1.a Selected Buckets 1024 of 1024 : all -> Index Scan using index_t2 on public.t2 Output: t2.a, t2.b, t2.c Distribute Key: t2.a Index Cond: (t2.a = t1.b) Selected Buckets 1024 of 1024 : all (ppi-pruning) (19 rows)
可以看到在Selected Buckets 这段有ppi-pruning标识,标识这个计划会执行参数化路径剪枝。
若需要知道具体的剪枝操作,可以在DN上执行explain analyze语句。
--直连DN。
gaussdb=# EXPLAIN (costs false,verbose on,analyze on) SELECT /*+ nestloop_index(t2, index_t2)*/* FROM t1 JOIN t2 on t1.b = t2.a;
QUERY PLAN
----------------------------------------------------------------------------------------
Nested Loop (actual time=4.743..10.928 rows=6 loops=1)
Output: t1.a, t1.b, t1.c, t2.a, t2.b, t2.c
-> Seq Scan on public.t1 (actual time=4.607..10.471 rows=6 loops=1)
Output: t1.a, t1.b, t1.c
Selected Buckets 1024 of 1024 : all
-> Index Scan using index_t2 on public.t2 (actual time=0.124..0.132 rows=6 loops=6)
Output: t2.a, t2.b, t2.c
Index Cond: (t2.a = t1.b)
Selected Buckets 1024 of 1024 : all (ppi-pruning) actual scan bucket num:6
Total runtime: 23.424 ms
(10 rows) 可以看到计划中有actual scan bucket num:6 这样一个字段,表示总共访问了6个bucket。
特性约束
- 支持bucket类型:hashbucket。
- 支持算子类型:indexscan、indexonlyscan、bitmapscan。
- 支持表达式类型:比较表达式(<,<=,=,>=,>)、逻辑表达式(and)。
- 不支持子查询表达式,不支持stable和volatile函数,不支持跨QueryBlock参数化路径,不支持BitmapOr、BitmapAnd算子。
- 只支持LBI(local bucket index) 不支持 cross bucket index。
- 只支持单分布列。
- 外连接驱动hashbucket表时,只支持=条件。
父主题: hashbucket