oracle非绑定变量忽略,避开绑定变量的弱点的一个经典解决方案——《Oracle高效设计》学习笔记...

假如我们在应用程序中对数据库进行查询时,经常会对某个字段使用Like语句,而数据库是对这个字段添加了索引的,如果查询的sql中like

的内容是以%开头的,那么索引很可能会被忽略,但当like的内容不是以%开头的,索引会被利用。假设这个查询会被经常使用,我们希望对

于这些查询使用绑定变量,这样可以减少硬解析的次数,但使用绑定变量的代价是,在查询时我们很可能使用错误的查询计划。

对于这个问题《Oracle高效设计》中给出了一个很经典的解决方案,使得我们在使用绑定变量同时,也能够使用正确的查询计划。

先做一个实验:

create table t

as

select a.* from all_objects a;

create index t_idx on t(object_name);

analyze table t compute statistics

for table for all indexes for all indexed columns;

variable x varchar2(50)

alter session set sql_trace=true;

set termout off

exec :x := '%';

select * from t x_was_percent where object_name like :x;

exec :x := 'Y%';

select * from t x_was_NOT_PCT where object_name like :x;

使用tkprof工具,查看跟踪结果:

BEGIN :x := '%'; END;

select *

from

t x_was_percent where object_name like :x

Misses in library cache during parse: 1Misses in library cache during execute: 1

Optimizer mode: ALL_ROWS

Parsing user id: 5

Rows     Row Source Operation

-------  ---------------------------------------------------

49654  TABLE ACCESS FULL T (cr=3950 pr=0 pw=0 time=198752 us)

BEGIN :x := 'Y%'; END;

select *

from

t x_was_NOT_PCT where object_name like :x

Misses in library cache during parse: 1Optimizer mode: ALL_ROWS

Parsing user id: 5

Rows     Row Source Operation

-------  ---------------------------------------------------

1  TABLE ACCESS BY INDEX ROWID T (cr=4 pr=0 pw=0 time=69 us)

1   INDEX RANGE SCAN T_IDX (cr=3 pr=0 pw=0 time=31 us)(object id 52917)

从测试结果可以看出,两个查询都使用了正确的查询计划。由于Oracle会在第一次执行绑定变量的sql时,

使用绑定变量窥视技术(根据绑定变量实际值确定查询计划),又因为,我们对于两个查询做了点改动(注意黑体,

第一条sql的t被命名为x_was_percent ,第二条sql的t被命名为x_was_NOT_PCT ),

使得Oracle把这两个相同的查询做为不同查询来看待,每个查询都解析了一遍,这就使得两个查询都使用了正确的

查询计划,只要保证程序,在后续的类似查询凡是以%号开头的,都使用第一条sql,如果不以%开头的都使用第二

条sql,就可以保证虽然使用了绑定变量,但每次查询都使用了正确的查询计划。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值