ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 绑定变量的使用范围

绑定变量的使用范围

原创 Linux操作系统 作者:wei-xh 时间:2010-05-08 19:53:22 0 删除 编辑
我们都知道绑定变量可以减少软解析。
可是对于表的数据倾斜列,使用绑定变量有个坏处,那就是优化器可能会产生性能低下的执行计划。
对于一个使用绑定变量的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博客 ” ,链接:https://blog.itpub.net/22034023/viewspace-662254/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 分区表学习之一
请登录后发表评论 登录
全部评论
Oracle ACE组成员,DBGeeK用户组发起人。曾在DTCC、ORACLE技术嘉年华、Gdevops等公开场合做过数据库技术专题分享,2017年应Oracle邀请在世界最大的数据库会议OOW上做技术分享。组织翻译了《拨云见日,解密Oracle ASM内核》一书。

注册时间:2009-07-04

  • 博文量
    422
  • 访问量
    2425317