BITMAP CONVERSION FROM ROWIDS
第一次写博客,虽然是转载,但也希望能坚持。
在有些执行计划中,可以会看到 BITMAP CONVERSION FROM ROWIDS这样的东东,也许你会感觉奇怪,我没有使用位图索引怎么出现了bitmap。
sql语句为:
SELECT *
FROM (SELECT a.*, ROWNUM rn
FROM ( SELECT module_no, MAX (id) AS id
FROM vasoa.tab_moa_historypage t
WHERE t.company_id = :1 AND t.user_id = :2 AND t.TYPE = :3
GROUP BY module_no
ORDER BY id DESC) a
WHERE ROWNUM <= :4) b
WHERE b.rn >= :5
执行计划为:
表结构为:
目前索引情况:
通过观察执行计划的图片可以发现,使用了 BITMAP CONVERSION FROM ROWIDS,其目的是:oracle将btree索引中获得的rowid信息通过BITMAP CONVERSION FROM ROWIDS的步骤转换成bitmap进行匹配,然后匹配完成后通过BITMAP CONVERSION TO ROWIDS再转换出rowid获得数据或者回表获得数据。这种想象出现的原因为:oracle的cbo是根据cost来决定大小来选择合适的执行计划,当它计算获得通过bitmap的方式执行的时候cost会更小,它就会选择使用这样的执行计划。一般出现这样的情况,都是因为对表建立的不适当的index导致,特别是对表中的唯一度不高的列建立了index,然后oracle就有可能选择两个这样的列转为为bitmap来执行。根据oracle的执行计划,肯定是cost最小的,但是它很多时候忽略了一致性读等其他条件,导致这个执行计划并非像oracle想象的那样最优,因为把btree index转为为bitmap index执行,需要消耗更多的cpu,特别是在cpu比较紧张的系统中,所以这样的情况如果发生在oltp系统中,一般都需要解决。
本例的解决办法有两种:
1、删除唯一度低的index,建立组合index。分别删除COMPANY_ID与USER_ID上的index,建立COMPANY_ID和USER_ID的组合index。
2、该hint提示也可以解决该问题:
/*+ opt_param(‘_b_tree_bitmap_plans’, ‘false’) */
OPT_PARAM可以让你在SQL级别通过加HINT的方式来调整单个SQL执行的时候所依赖的系统参数的值。
转自:http://www.xifenfei.com/2011/09/bitmap-conversion-from-rowids.html
另:
这和隐含参数"_b_tree_bitmap_plans"
有关,11G默认是true,同时在where条件中出现两条以上的选择条件,而且都有索引,就有可能出现BITMAP CONVERSION FROM ROWIDS。
我在自己做试验时发现如果不走 BITMAP CONVERSION FROM ROWIDS,有时反而cost会比较高,所以出现这种情况不一定必须要优化。存在即合理吧。如果SQL慢,且执行计划有BITMAP CONVERSION FROM ROWIDS,可以用上面的方法试试。
查询隐含参数的语句
SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ
FROM SYS.x$ksppi x, SYS.x$ksppcv y
WHERE x.inst_id = USERENV ('Instance')
AND y.inst_id = USERENV ('Instance')
AND x.indx = y.indx
AND x.ksppinm LIKE '%&par%';