
# 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的数据，减少无意义的读取。
![](https://support.huaweicloud.com/distributed-devg-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
关于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表时，只支持=条件。
 
