lightdb-pq_distribute hint

Posted 紫无之紫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lightdb-pq_distribute hint相关的知识,希望对你有一定的参考价值。

文章目录

LightDB pq_distribute hint

LightDB 从 22.3 版本开始支持 oralce 的 pq_distribute hint, 目前只支持 none,broadcasthash,hash两种模式,其中hash,hash 不生效。

一. LightDB parallel join 介绍

lightdb 并发 join 支持两种模式,一种是只有外表并发,一种则内外表都可以并发(只支持hash join)。

1.1 外表并发

此模式下只有外表并发,内表广播,每个worker都会访问全量内表。Nestloop, mergejoin 只能采用此模式,hashjoin 可以采用此模式。以 hashjoin 为例,每个 worker 都会根据内表生成一个全量的hash表,每个 worker的 hash 表都相同。

在 explain 下显示为 Hash Join

                 QUERY PLAN                  
---------------------------------------------
 Gather
   Workers Planned: 3
   ->  Hash Join
         Hash Cond: (t1.id = t2.id)
         ->  Parallel Seq Scan on t1 @"lt#0"
         ->  Hash
               ->  Seq Scan on t2 @"lt#0"
(7 rows)

这种模式类似 oracle 的 none,broadcast 模式

1.2 内外表都并发 Parallel Hash Join

此模式下外表并发,内表也支持并发,目前只有 hashjoin 支持。 会对内表并发的生成一个共享的 hash 表。需要等待内表生成完共享的 hash 表后,才能开始并发 join。


在 explain 下显示为 Parallel Hash Join

                    QUERY PLAN                     
---------------------------------------------------
 Gather
   Workers Planned: 3
   ->  Parallel Hash Join
         Hash Cond: (t2.id = t1.id)
         ->  Parallel Seq Scan on t2 @"lt#0"
         ->  Parallel Hash
               ->  Parallel Seq Scan on t1 @"lt#0"
(7 rows)

在oracle中没有类似的模式

1.3 note

oracle 中的 hash, hash 模式在 LightDB 中不支持,故只支持语法,oracle 的其他模式在 23.1 暂不支持,计划后续版本支持,至少会支持语法(为了更好迁移)。

二. hint 介绍及使用

2.1 语法

pq_distribute(inner_table outer_distribution inner_distribution)
  • inner_table: 指定 join 中的内表名
  • outer_distribution:指定外表的模式
  • inner_distribution:指定内表的模式

outer_distribution,inner_distribution 可选的组合目前有:none, broadcasthash, hash。其中hash, hash只支持语法。

  • none, broadcast: 表示外表并发,内表广播
  • hash, hash: 在 oracle 中表示 使用 hash 函数对内外表数据进行分区,然后一一映射,一一关联。在 LightDB 中不支持此模式。

使用 pq_distribute hint 只是让优化器在选择指定的表作为关联的内表且关联模式为parallel hash join 时,改变 j改变模式为none, broadcast。

2.2 使用案例

2.2.1 准备

create table t1 (id int, val text);
create table t2 (id int, val text);

2.2.2 测试案例

  • 使用 /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/ 来使 join 选择 parallel join。

  • 使用 leading(t1 t2) hashjoin(t1 t2) 来指定 join 为 hashjoin 并指定 join 顺序

  • 使用 pq_distribute(t2 none broadcast) 来使用外表并发,内表广播的方式。


lightdb@lt_test=# /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/
lightdb@lt_test-# EXPLAIN (COSTS false) SELECT /*+ leading(t1 t2) hashjoin(t1 t2)*/ * FROM t1 join t2 on t1.id=t2.id;
                    QUERY PLAN                     
---------------------------------------------------
 Gather
   Workers Planned: 3
   ->  Parallel Hash Join
         Hash Cond: (t1.id = t2.id)
         ->  Parallel Seq Scan on t1 @"lt#0"
         ->  Parallel Hash
               ->  Parallel Seq Scan on t2 @"lt#0"
(7 rows)

lightdb@lt_test=# /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/
lightdb@lt_test-# EXPLAIN (COSTS false) select/*+leading(t1 t2) hashjoin(t1 t2) pq_distribute(t2 none broadcast)*/ * from t1 join t2 on t1.id=t2.id;
                 QUERY PLAN                  
---------------------------------------------
 Gather
   Workers Planned: 3
   ->  Hash Join
         Hash Cond: (t1.id = t2.id)
         ->  Parallel Seq Scan on t1 @"lt#0"
         ->  Hash
               ->  Seq Scan on t2 @"lt#0"
(7 rows)

lightdb@lt_test=#  
  • 在于 swap_join_inputs 一起用时,swap_join_inputs 生效的话,pq_distribute 也会生效(原先为parallel hashjoin)。这与 oracle 不同,在 oracle 中 swap_join_inputs 生效,但如果 pq_distribute 与 swap_join_inputs 指定的不是同一张表,则 pq_distribute 不会起效。
lightdb@lt_test=# /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/
EXPLAIN (COSTS false) select/*+leading(t1 t2) hashjoin(t1 t2) pq_distribute(t1 none broadcast)*/ * from t1 join t2 on t1.id=t2.id;
                    QUERY PLAN                     
---------------------------------------------------
 Gather
   Workers Planned: 3
   ->  Parallel Hash Join
         Hash Cond: (t1.id = t2.id)
         ->  Parallel Seq Scan on t1 @"lt#0"
         ->  Parallel Hash
               ->  Parallel Seq Scan on t2 @"lt#0"
(7 rows)

lightdb@lt_test=# /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/
EXPLAIN (COSTS false) select/*+leading(t1 t2) hashjoin(t1 t2) pq_distribute(t1 none broadcast) swap_join_inputs(t2)*/ * from t1 join t2 on t1.id=t2.id;
                 QUERY PLAN                  
---------------------------------------------
 Gather
   Workers Planned: 3
   ->  Hash Join
         Hash Cond: (t2.id = t1.id)
         ->  Parallel Seq Scan on t2 @"lt#0"
         ->  Hash
               ->  Seq Scan on t1 @"lt#0"
(7 rows)

lightdb@lt_test=# /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/
EXPLAIN (COSTS false) select/*+leading(t1 t2) hashjoin(t1 t2) pq_distribute(t2 none broadcast) swap_join_inputs(t2)*/ * from t1 join t2 on t1.id=t2.id;
                 QUERY PLAN                  
---------------------------------------------
 Gather
   Workers Planned: 3
   ->  Hash Join
         Hash Cond: (t2.id = t1.id)
         ->  Parallel Seq Scan on t2 @"lt#0"
         ->  Hash
               ->  Seq Scan on t1 @"lt#0"
(7 rows)

lightdb@lt_test=#  
  • 如果没有指定 hashjoin 的顺序,没有使用 pq_distribute 时 t2 是内表,使用了 pq_distribute 后,执行计划还是Parallel Hash Join, 但内表变为了 t1, 看起来像是 pq_distribute 没起效。
lightdb@lt_test=# /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/
EXPLAIN (COSTS false) select/*+hashjoin(t1 t2)pq_distribute(t2 none broadcast)*/ * from t1 join t2 on t1.id=t2.id;
                    QUERY PLAN                     
---------------------------------------------------
 Gather
   Workers Planned: 3
   ->  Parallel Hash Join
         Hash Cond: (t2.id = t1.id)
         ->  Parallel Seq Scan on t2 @"lt#0"
         ->  Parallel Hash
               ->  Parallel Seq Scan on t1 @"lt#0"
(7 rows)

lightdb@lt_test=# /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/
EXPLAIN (COSTS false) select/*+hashjoin(t1 t2)pq_distribute(t1 none broadcast)*/ * from t1 join t2 on t1.id=t2.id;
                    QUERY PLAN                     
---------------------------------------------------
 Gather
   Workers Planned: 3
   ->  Parallel Hash Join
         Hash Cond: (t1.id = t2.id)
         ->  Parallel Seq Scan on t1 @"lt#0"
         ->  Parallel Hash
               ->  Parallel Seq Scan on t2 @"lt#0"
(7 rows)

lightdb@lt_test=# /*+set(parallel_tuple_cost 0) set(parallel_setup_cost 0) set(min_parallel_table_scan_size 0) set(min_parallel_index_scan_size 0) set(max_parallel_workers_per_gather 8)*/
EXPLAIN (COSTS false) select/*+hashjoin(t1 t2)pq_distribute(t1 none broadcast) pq_distribute(t2 none broadcast)*/ * from t1 join t2 on t1.id=t2.id;
                 QUERY PLAN                  
---------------------------------------------
 Gather
   Workers Planned: 3
   ->  Hash Join
         Hash Cond: (t1.id = t2.id)
         ->  Parallel Seq Scan on t1 @"lt#0"
         ->  Hash
               ->  Seq Scan on t2 @"lt#0"
(7 rows)

lightdb@lt_test=#   

以上是关于lightdb-pq_distribute hint的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB中的explain和hin提的使用

Default value for parameters with a class type hin

一篇含金量hin高的Nginx反向代理与负载均衡指南

我用开天平台做了一个字符串检查API,hin 简单~~

逆卷积:convtranspose2d(fractionally-strided convolutions)

使用 LIKE 子句搜索 Mysql