HelloDBA [English]
搜索Internet 搜索 HelloDBABA
  Oracle技术站。email: fuyuncat@gmail.com  MSN: fuyuncat@hotmail.com   acoug  acoug 

CBO 中如何计算调整的MBRC

[English]

作者: fuyuncat

来源: www.HelloDBA.com

日期: 2010-03-10 07:30:12

分享到  新浪微博 腾讯微博 人人网 i贴吧 开心网 豆瓣 淘宝 推特 Facebook GMail Blogger Orkut Google Bookmarks

    在CBO的IO模式中,全表扫描的IO代价不是直接由MBRC(db_file_multiblock_read_count)计算来的,而是由一个相应的调整的值(ADJMBRC)计算的:
    IO = 1+CEIL(TABBLKS/ADJMBRC)

    Jonathan Lewis曾经讨论过ADJMBRC是由MBRC和数据块大小决定的,以8k数据块大小为例,相应的ADJMBRC是

SQL代码
  1. MBRC         ADJMBRC   
  2. ------------ --------------   
  3. 8            6.59   
  4. 16           10.40   
  5. 32           16.41   
  6. 64           25.90  

    可以看到,ADJMBRC是一些ROUND过的值,且看起来似乎无规律。我们这里做个数字游戏,看看这些数字直接是否有没有规律。

    由之前的公式,可知ADJMBRC计算如下:
    ADJMBRC ≈ TABBLKS/(IO - 1)

    我们通过测试,调整TABBLKS,可以发现ADJMBRC会逐渐接近某个数字。以MBRC=16为例,其ADJMBRC接近为6.588755338...,同样可得到其他MBRC的ADJMBRC为

SQL代码
  1. MBRC         ADJMBRC   
  2. ------------ --------------   
  3. 8            6.588755338   
  4. 16           10.39779676   
  5. 32           16.4088924   
  6. 64           25.89507721   

    虽然精度提高了,但是规律还是不可寻。我们尝试计算ADJMBRC/MBRC看看会有什么结果:

SQL代码
  1. MBRC         ADJMBRC        ADJMBRC/MBRC   
  2. ------------ -------------- -------------   
  3. 8            6.588755338    0.823594417   
  4. 16           10.39779676    0.649862298   
  5. 32           16.4088924     0.512777888   
  6. 64           25.89507721    0.404610581  

    嗯,还是看不到规律。不过注意到,我们这的MBRC直接是倍数关系,那么再试试将ADJMBRC/MBRC的结果前后相除会有什么结果: 

SQL代码
  1. MBRC         ADJMBRC        ADJMBRC/MBRC  (ADJMBRC/MBRC[n*2])/(ADJMBRC/MBRC[n])   
  2. ------------ -------------- ------------- -------------------------------------   
  3. 8            6.588755338    0.823594417   1.26733682   
  4. 16           10.39779676    0.649862298   1.26733682   
  5. 32           16.4088924     0.512777888   1.26733682   
  6. 64           25.89507721    0.404610581  

    哈,这下找到了。由上面的推导过程,也就不难得出ADJMBRC的公式了:
    ADJMBRC = 1.6764459346/POWER(1.26733682,LOG(MBRC,2))*MBRC

    再考虑BLKSIZ因素,上述公式就可以调整为:
    ADJMBRC = 1.6764459346/POWER(1.26733682,LOG(8192/BLKSIZ*MBRC,2))*8192/BLKSIZ*MBRC

    对1.6764459346取反,可知其为(1/0.5965)。但是我仍然没有看出1.26733682是如何来的。上述公式调整为:
    ADJMBRC = 1/0.5965/POWER(1.26733682,LOG(8192/BLKSIZ*MBRC,2))*8192/BLKSIZ*MBRC

    有了上述公式,我们就不难通过SQL来估算表(或分区)的Full Table Scan的IO代价了: 

SQL代码
  1. HELLODBA.COM>select p.value mbrc,   
  2.   2         1/0.5965/POWER(1.26733682,LOG(2,8192/sp.block_size*p.value))*8192/sp.block_size*p.value adjmbrc,   
  3.   3         s.blocks,   
  4.   4         1+ceil(s.blocks/(1/0.5965/POWER(1.26733682,LOG(2,8192/sp.block_size*p.value))*8192/sp.block_size*p.value)) IOCOST   
  5.   5  from dba_segments s, dba_tablespaces sp, all_parameters p   
  6.   6  where s.owner='DEMO' and s.segment_name = 'T_TEST1'  
  7.   7  and s.tablespace_name = sp.tablespace_name   
  8.   8  and p.name = 'db_file_multiblock_read_count';   
  9.   
  10. MBRC   ADJMBRC     BLOCKS     IOCOST   
  11. ------ ----------- ---------- ----------   
  12. 16     10.3977968  680        67   
  13.   
  14. HELLODBA.COM>set autot trace exp   
  15. HELLODBA.COM>select /*+no_cpu_costing*/* from demo.t_test1;   
  16.   
  17. Execution Plan   
  18. ----------------------------------------------------------   
  19. Plan hash value: 1883417357   
  20.   
  21. -------------------------------------------------------------   
  22. | Id  | Operation         | Name    | Rows  | Bytes | Cost  |   
  23. -------------------------------------------------------------   
  24. |   0 | SELECT STATEMENT  |         | 47582 |  4600K|    67 |   
  25. |   1 |  TABLE ACCESS FULL| T_TEST1 | 47582 |  4600K|    67 |   
  26. -------------------------------------------------------------   

    --- Fuyuncat ---

Top

Copyright ©2005,HelloDBA.Com 保留一切权利

申明
by fuyuncat