转载:遇到BITMAP CONVERSION TO ROWIDS 后解决与思考

今天遇到一个案例,有点价值写下来,以后多看看

SQL:

select t.order_id,   t.spec_name,   t.staff_code,  t.staff_code  as xxbStaffCode,     t.channel_id  as xxbChannelId,
       t.area_code,  t.create_time,    t.id_card
  from  zmkm_intent_order t,  zmkm_order_ext_val s
 where t.order_id = s.order_id
   and exists (select 1
          from JS_SERVICE.zmkm_order_ext_val k
         where k.order_Id = t.order_id
           and k.param_id = '100007'
           and k.ext_val = '18190044')
   and t.deal_flag = 0
   and t.area_code = '0516';

执行计划:





SQL的性能瓶颈在ID = 3.仔细看E-rows 才330条, 偏小很多。 但是为啥是 330呢。

分别explain  plan for

select count(1) from  zmkm_order_ext_val k   where  k.param_id = '100007';
 select count(1) from  zmkm_order_ext_val k  where k.ext_val = '18190044'

rows 第一个是21万, 第二个是5千。但是BITMAP CONVERSION TO ROWIDS参与后就330.

就是因为rows 估算成330,导致这个搞成驱动表。  因此导致两个索引合并后真实数据量是9千, 大量的回表K。造成了性能问题。

如果这边搞成被驱动表, 那么显然就是根据索引访问K。并且此时驱动表的数据也不多,大概是 1000多条 NL下去也是不错的。

想到这边差不多知道答案了。期间尝试 数次  cardinality hint 无果。

SQL>  alter session set "_b_tree_bitmap_plans"=false;

会话已更改。

 

已选择352行。


执行计划
----------------------------------------------------------
Plan hash value: 141468126

----------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name               | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                    |  5254 |   815K|  2288   (1)| 00:00:28 |
|   1 |  NESTED LOOPS                 |                    |  5254 |   815K|  2288   (1)| 00:00:28 |
|   2 |   NESTED LOOPS SEMI           |                    |   330 | 44880 |  1627   (0)| 00:00:20 |
|   3 |    TABLE ACCESS BY INDEX ROWID| ZMKM_INTENT_ORDER  |   405 | 39285 |     7   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN          | IDX_ACODE_DFLAG    |   405 |       |     1   (0)| 00:00:01 |
|*  5 |    TABLE ACCESS BY INDEX ROWID| ZMKM_ORDER_EXT_VAL |   269 | 10491 |     4   (0)| 00:00:01 |
|*  6 |     INDEX RANGE SCAN          | IDX_ORDER_ID       |    16 |       |     2   (0)| 00:00:01 |
|*  7 |   INDEX RANGE SCAN            | IDX_ORDER_ID       |    16 |   368 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------

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

   4 - access("T"."AREA_CODE"='0516' AND "T"."DEAL_FLAG"=0)
   5 - filter("K"."EXT_VAL"='18190044' AND "K"."PARAM_ID"='100007')
   6 - access("K"."ORDER_ID"="T"."ORDER_ID")
   7 - access("T"."ORDER_ID"="S"."ORDER_ID")


统计信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       4518  consistent gets
          0  physical reads
          0  redo size
      13485  bytes sent via SQL*Net to client
        725  bytes received via SQL*Net from client
         25  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        352  rows processed

alter session set "_b_tree_bitmap_plans"=false;--- 加入这个后逻辑读减少到  4518。

 但是还有其他办法吗??  答案是有的。

 看到有问题的执行计划, 就是在两个索引合中取数据, 那么如果建立组合索引, 把该要的数据全部集中在索引中。

那么就没有必要在两个索引中取数据了。 建立索引 index ( PARAM_ID,EXT_VAL, ORDER_ID);  也就是9万多数据。

应该在7百个逻辑读左右。 结合另一张表访问也是7百个逻辑读。 不过此时hash 。 能控制在 1600 逻辑读左右。

1 适合用sqlprofile 立即绑定执行计划 ,适合线上快速改变执行计划

2 适合实施简单方便, 因为有些时候 DBA和业务是隔开的, 让业务绑定执行计划,反正我是没有去交接过。 不如扔一个建索引语句,说建立一下即可。
--------------------- 
作者:越烟 
来源:CSDN 
原文:https://blog.csdn.net/daiqiulong2/article/details/88824518 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自www.cnblogs.com/chendian0/p/10611416.html