oracle中bind peeking问题的解决方法

使用绑定变量可以减少SQL PARSE,但是使用绑定变量有一个不好的地方,就是对于访

问具有倾斜的列,可能使用错误的执行计划。在Oracle 9i之前,如果WHERE 条件里面全

部使用绑定变量,那么只能使用固定的选择性参数来确定执行计划。

=操作和>=操作的选择性为5%,范围扫描的选择性为25%。缺省值的方式可能生成不好的执

行计划。所以Oracle 9i就出现了一个新的技术,bind peeking。什么是bind peeking呢

?当SQL第一次执行的时候,优化器会根据绑定变量来确定执行计划(如果存在柱状图)

。BIND PEEKING只有当该SQL第一次执行的时候,进行HARD PARSE的时候才进行,第二次

调用该SQL,就不会再次进行BIND PEEKING。这种情况下,就存在另外一个风险,如果某

个列的倾斜性很厉害,那么使用BIND PEEKING就是不安全的,因为不同的参数代入,只能

走第一次执行时的执行计划,那么执行计划就像掷色子一样,要靠运气了。碰到这种情况

,应用就不应该使用绑定变量,而应该改为直接值了。
  这时可以使用刷新一下共享池alter system flush shared_pool;
  或者alter session set "_optim_peek_user_binds"=false;

   我们可以通过隐含的参数来调整数据库默认的bind peeking行为:

_OPTIM_PEEK_USER_BINDS。 如果我们想关闭Bind Variable Peeking,我们可以设置该参

数为 False 即可。

SQL>alter session set "_optim_peek_user_binds"=false


使用了Bind Var能提高性能主要是因为这样做可以尽量避免不必要的硬分析(Hard Parse)

而节约了时间,同时节约了大量的CPU资源。

    当一个Client提交一条Sql给Oracle后,Oracle 首先会对其进行解析(Parse),然后

将解析结果提交给优化器(Optimiser)来进行优化而取得Oracle认为的最优的Query Plan

,然后再按照这个最优的Plan来执行这个Sql语句(当然在这之中如果只需要软解析的话会

少部分步骤)。

当Oracle接到 Client提交的Sql后会首先在共享池(Shared Pool)里面去查找是否有之前

已经解析好的与刚接到的这一个Sql完全相同的Sql(注意这里说的是完全相同,既要求语

句上的字符级别的完全相同,又要求涉及的对象也必须完全相同)。当发现有相同的以后

解析器就不再对新的Sql在此解析而直接用之前解析好的结果了。这里就节约了解析时间

以及解析时候消耗的CPU资源。尤其是在OLTP中运行着的大量的短小Sql,效果就会比较明

显了。因为一条两条Sql的时间可能不会有多少感觉,但是当量大了以后就会有比较明显

的感觉了。


但是,使用绑定变量的一个缺点是,给出的执行计划并不一定就是SQL在真正应用程序里

所使用的执行计划。这时我们就可以通过 event 10053 事件来查看。

posted @ 2012-02-20 15:55  sky7034  阅读(928)  评论(0编辑  收藏  举报
蘑菇街女装 货运专家