Oracle对Sql语句的软解析和硬解析?

经常在论坛中,有人会在针对SQL优化方向提出:要避免SQL进行硬解析,从而提高SQL执行的效率。避免硬解析,确实是高效利用shared_pool的一种重要策略。通常情况下,作为开发人员,我们需要记住,为了最高效的利用共享池,我们编写的sql最好是可以共享的,比如绑定变量就是一个避免硬解析从而提高共享的有效手段。我们举一个相对极端的例子,在这里我们使用动态sql来模拟硬解析的场景:

ChenZw> drop table foo purge;

表已删除。

已用时间: 00: 00: 00.05
ChenZw> create table foo (x int);

表已创建。

已用时间: 00: 00: 00.07

ChenZw> create or replace procedure proc
2 as
3 begin
4 for i in 1..100000 loop
5 execute immediate
6 'insert into foo values ('||i||')';
7 end loop;
8 end;
9 /

过程已创建。

已用时间: 00: 00: 00.05
ChenZw> exec proc;

PL/SQL 过程已成功完成。

已用时间: 00: 00: 47.75
ChenZw>

可以看到上面的执行时间是47.75秒,我们可以去查看能够体现Shared_pool里面共享sql区域中的一个数据字典中的内容:

我们发现在其中,最早的那个解析是插入96581的那条数据,最末的解析是插入100000的那条解析,一共是6281条数据。

现在我们换一种方式重新来执行上面的语句,我们使用动态sql的绑定变量的方式来写这个sql语句,我们尝试的代码和结果如下:

ChenZw> drop table foo purge;

表已删除。

已用时间: 00: 00: 00.13
ChenZw> create table foo (x int);

表已创建。

已用时间: 00: 00: 00.03
ChenZw> drop procedure proc;

过程已删除。

已用时间: 00: 00: 00.04
ChenZw> create or replace procedure proc
2 as
3 begin
4 for i in 1..100000 loop
5 execute immediate
6 'insert into foo values (:x)' using i;
7 end loop;
8 end;
9 /

过程已创建。

已用时间: 00: 00: 00.06
ChenZw> alter system flush shared_pool;

系统已更改。

已用时间: 00: 00: 00.92
ChenZw> exec proc;

PL/SQL 过程已成功完成。

已用时间: 00: 00: 04.50
ChenZw>

我们查看保存在v$sql中的内容,可以看到如下的内容:


可以很清楚的看到,插入语句被解析了一次,而调用了十万次,因此,执行效率从第一次的48秒钟,变为现在的5秒钟。

那两个到底有什么区别呢?这个例子跟sql语句的软解析和硬解析又有什么关系呢?

下面是Oracle Concepts Guide中给出的图:

先给出一个结论好了,上面第一种情况,就是sql硬解析次数太多而导致了执行效率低下,第二种情况,因为降低了sql的硬解析,从而提高了sql的运行效率。

第一种情况,当第一条insert into foo values (1)执行的时候,因为没有采用绑定变量的方式,因此在上述结构图的SGA中,首先对该条语句进行判断语法校验,确认权限等等各种准备工作之后,通过hash得形成一个解析后的信息,放置到SGA中。然后当insert into foo values (2)来执行的时候呢,做了同样的工作。

第二种情况,当第一条insert into foo values (:x)执行的时候,也是对该条语句进行语法判断等等准备工作之后,将解析之后的信息,放到了SGA当中,但是当第二条语句来到的时候,Oracle就不需要再做结息的工作了,直接将上一次执行之后的结果拿出来运行就好了。

所以,我们可以看到软解析和硬解析的区别了。

如果Oracle在sql进行解析的时候,能够从SGA中找到之前曾经解析过的信息直接执行的情况,被称作SQL的软解析。如果Oracle在sql进行解析的时候,找不到可以拿来就用的sql,必须重新解析信息的情况,就是SQL的硬解析,sql的软解析与硬解析在效率上大概有接近50-60倍性能的差距(源自某个论坛上一个Oracle
高手的试验结果,具体地址忘记了)。

--作者 陈字文(热衷于PM\ORACLE\JAVA等,欢迎同行交流):ziwen#163.com 扣扣:4零9零2零1零零

另外,通过上面的例子可以看到,存储解析结果的内存空间并不是非常大的,例如我们第一个例子,解析了10万次,但是仅仅存放了6281条解析后的数据。通过对相关语句的分析,我们也可以知道,该块内存的算法应该是最近最少使用算法。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值