用hash分发模式解决并行优化器bug

背景

最近给项目做性能优化,遇到一个并行优化器bug,场景是简单的2张300W表做内关联,开的8个并行,走的hash连接,但是性能特别差,拿到执行计划是走了broadcast分发模式,这明显不对,应该走hash分发模式。当时以为是统计信息不准确导致,收集完统计信息以后,执行计划并没有改变,猜测是oracle优化器的Bug。

broadcast广播分发

通俗来讲就是将其中一张表全量结果集传输到其他拥有另一张表部分结果集的多个进程上做关联,非常试用于小表与大表的分发场景

hash分发

将两张表采用关联键进行hash运算分发,这样每个并行服务器上只有各自一部分不重复结果集关联,适合大表与大表的分发场景,这种分发模式可以手工实现优化超级大表的关联。

实验

1.创建2个测试表
create table test1 as select * from dba_objects;
create table test2 as select * from dba_objects;
2.复现broadcast分发模式
select/*+ optimizer_features_enable('11.2.0.4')  parallel(4) pq_distribute(a broadcast none)*/ *
from test1 a, test2 b
where a.object_id=b.object_id
--执行计划
----------------------------------------------------------
Plan hash value: 1728626078

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |          | 71566 |    65M|   215   (2)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR         |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)   | :TQ10001 | 71566 |    65M|   215   (2)| 00:00:01 |  Q1,01 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN            |          | 71566 |    65M|   215   (2)| 00:00:01 |  Q1,01 | PCWP |            |
|   4 |     PX RECEIVE          |          | 71566 |    32M|   107   (1)| 00:00:01 |  Q1,01 | PCWP |            |
|   5 |      PX SEND BROADCAST  | :TQ10000 | 71566 |    32M|   107   (1)| 00:00:01 |  Q1,00 | P->P | BROADCAST  |
|   6 |       PX BLOCK ITERATOR |          | 71566 |    32M|   107   (1)| 00:00:01 |  Q1,00 | PCWC |            |
|   7 |        TABLE ACCESS FULL| TEST2    | 71566 |    32M|   107   (1)| 00:00:01 |  Q1,00 | PCWP |            |
|   8 |     PX BLOCK ITERATOR   |          | 92106 |    42M|   107   (1)| 00:00:01 |  Q1,01 | PCWC |            |
|   9 |      TABLE ACCESS FULL  | TEST1    | 92106 |    42M|   107   (1)| 00:00:01 |  Q1,01 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("A"."OBJECT_ID"="B"."OBJECT_ID")

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - Degree of Parallelism is 4 because of hint


统计信息
----------------------------------------------------------
         47  recursive calls
          0  db block gets
       3490  consistent gets
       1105  physical reads
          0  redo size
    8448172  bytes sent via SQL*Net to client
      53574  bytes received via SQL*Net from client
       4826  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
      72364  rows processed
3.用hash分发调整执行计划
select/*+ optimizer_features_enable('11.2.0.4')  parallel(4) pq_distribute(a hash hash)*/ *
from test1 a, test2 b
where a.object_id=b.object_id
--执行计划
----------------------------------------------------------
Plan hash value: 2213618322

-----------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |          | 71566 |    65M|   215   (2)| 00:00:01 |        |      |            |
|   1 |  PX COORDINATOR         |          |       |       |            |          |        |      |            |
|   2 |   PX SEND QC (RANDOM)   | :TQ10002 | 71566 |    65M|   215   (2)| 00:00:01 |  Q1,02 | P->S | QC (RAND)  |
|*  3 |    HASH JOIN BUFFERED   |          | 71566 |    65M|   215   (2)| 00:00:01 |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE          |          | 71566 |    32M|   107   (1)| 00:00:01 |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH       | :TQ10000 | 71566 |    32M|   107   (1)| 00:00:01 |  Q1,00 | P->P | HASH       |
|   6 |       PX BLOCK ITERATOR |          | 71566 |    32M|   107   (1)| 00:00:01 |  Q1,00 | PCWC |            |
|   7 |        TABLE ACCESS FULL| TEST2    | 71566 |    32M|   107   (1)| 00:00:01 |  Q1,00 | PCWP |            |
|   8 |     PX RECEIVE          |          | 92106 |    42M|   107   (1)| 00:00:01 |  Q1,02 | PCWP |            |
|   9 |      PX SEND HASH       | :TQ10001 | 92106 |    42M|   107   (1)| 00:00:01 |  Q1,01 | P->P | HASH       |
|  10 |       PX BLOCK ITERATOR |          | 92106 |    42M|   107   (1)| 00:00:01 |  Q1,01 | PCWC |            |
|  11 |        TABLE ACCESS FULL| TEST1    | 92106 |    42M|   107   (1)| 00:00:01 |  Q1,01 | PCWP |            |
-----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("A"."OBJECT_ID"="B"."OBJECT_ID")

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)
   - Degree of Parallelism is 4 because of hint


统计信息
----------------------------------------------------------
         47  recursive calls
          0  db block gets
       3486  consistent gets
        992  physical reads
          0  redo size
   10065498  bytes sent via SQL*Net to client
      53569  bytes received via SQL*Net from client
       4826  SQL*Net roundtrips to/from client
          2  sorts (memory)
          0  sorts (disk)
      72364  rows processed
4.分析
使用optimizer_features_enable('11.2.0.4')这个hint是复现当时场景,本地安装的是19c版本使用自适应的并行分发方法,hybrid hash分发模式,这里不过多介绍。
简单从逻辑读consistent gets观察,二者区别不大,但是区别在于广播大表的消耗与做hash分发消耗,以及笔者认为最重要的是hash table的大小是否能完全容纳于内存,从而导致大量临时表空间读写消耗。

总结

要理解并发每种分发模式原理,这样即使遇到oracle自身Bug我们也可以游刃有余。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值