绑定变量的使用范围

本文通过实例演示了在Oracle数据库中使用绑定变量时可能产生的性能问题。特别是在数据倾斜的情况下,优化器生成的执行计划可能不是最优选。文章对比了使用与不使用绑定变量时的不同执行计划。
我们都知道绑定变量可以减少软解析。
可是对于表的数据倾斜列,使用绑定变量有个坏处,那就是优化器可能会产生性能低下的执行计划。
对于一个使用绑定变量的SQL语句,第一次执行的时候,优化器会使用一个叫做BIND PEEKING的技术,对绑定变量的值进行绑定窥探(BAND PEEKING),来生成执行计划,以后再执行同样的语句,会依赖于第一次执行时的执行计划。
对于数据倾斜列,由于BIND PEEKING的特点,可能会产生性能非常低下的执行计划。
下面看看测试情况:
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
1)不使用绑定变量的情况。
测试表tab,其中列B为倾斜列。
SQL> desc tab;
名称    是否为空?                类型
  a                             number
  b                             number
SQL> select b,count(1) from tab group by b;


         B   COUNT(1)
---------- ----------
         1          1
         2          1
         3          1
         4          1
         5       9991
      9996          1
      9997          1
      9998          1
      9999          1
     10000          1
可以看出列值等于5的占了绝大数。

create index ind_tab_b on tab(b);
分析表:
BEGIN
  DBMS_STATS.GATHER_TABLE_STATS(OWNNAME    => 'SCOTT',
                                TABNAME    => 'TAB',
                                CASCADE    => TRUE);
END;

然后执行查询:
SQL> select * from tab where b=1;
         A          B
---------- ----------
         1          1

已用时间:  00: 00: 00.00
SQL> select * from table(dbms_xplan.display_cursor);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------
--------
SQL_ID  8vjf9k7jrfbh5, child number 0
-------------------------------------
select * from tab where b=:"SYS_B_0"

Plan hash value: 1668701379
------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |       |       |     2 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| TAB  |     1 |     6 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | SS   |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------

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

   2 - access("B"=:SYS_B_0)

已选择19行。
已用时间:  00: 00: 00.17

SQL> select * from tab where b=5;
已用时间:  00: 00: 00.00

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

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  9991 | 59946 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| TAB  |  9991 | 59946 |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter("B"=5)

可以看到产生了我们预想的正确的执行计划。


[ 本帖最后由 wei-xh 于 2010-5-8 19:49 编辑 ]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22034023/viewspace-662254/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/22034023/viewspace-662254/

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值