Oracle的硬解析和软解析

提到软解析(soft parse)和硬解析(hard parse),就不能不说一下Oracle对SQL的处理过程.当你发出一条SQL语句交付给Oracle,在执行和获取结果前,Oracle对此SQL进行几个步骤的处理过程。

1.语法检查(syntax check)

检查此sql的拼写是否是否符合语法要求.

2. 语义检查(semantic check)

诸如检查sql语句的访问对象是否存在及用户是否具备相应的权限.

3.对sql语句进行解析(parse)

利用内部算法对sql进行解析,生成解析树(parse tree)及执行计划(execution plan).

4.执行sql,返回结果(execute and return)

其中,软,硬解析就发生在第三个过程里.

Oracle利用内部的hash算法来取得该sql的hash值,然后在library cache里查找是否存在该hash值;

假设存在,则将此sql与cache中的进行比较;

假设“相同”,则将利用已有的解析树与执行计划,而省略了优化器的相关工作。这也是软解析的过程。

诚然,如果上面的2个假设有一个不成立,那么优化器将进行创建解析树,生成执行计划的动作.这个过程就叫硬解析.

在sql中应该尽量避免硬解析,下面为使用非绑定变量和绑定变量的情况:

--创建测试表

create table test
(
   id1 number,
   id2 number
);

--查询存在的 parse count (解析数)

select name, value from v$mystat a , v$statname b
where a.STATISTIC#=b.STATISTIC#
and name like 'parse count%';

    NAME                VALUE
1 parse count (total) 56
2 parse count (hard) 7
3 parse count (failures) 0


--(硬解析)
begin
  for i in 1..10000 loop
    execute immediate 'insert into test values (' ||i||','||i|| ') ' ;
  end loop;
  commit;
end;

--已用时间:  00: 00: 05.08

--查询执行sql后的 parse count (解析数)

select name, value from v$mystat a, v$statname b
where a.STATISTIC#=b.STATISTIC#
and name like 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   10064
parse count (hard)                                                    10011   硬解析次数为 10011-7
parse count (failures)                                                    0

-- 查询shared_pool的关于执行insert into test语句的cache
select s.SQL_TEXT,s.VERSION_COUNT,s.PARSE_CALLS, s.EXECUTIONS  
from v$sqlarea s where s.SQL_TEXT like '%test%';

--alter system flush shared_pool; 清空共享池
********************************************************************
--使用绑定变量的情况
--查询存在的 parse count (解析数)
select name, value from v$mystat a , v$statname b
where a.STATISTIC#=b.STATISTIC#
and name like 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                     171
parse count (hard)                                                       36
parse count (failures)                                                    0

--(软解析)
begin
  for i in 1..10000 loop
    execute immediate 'insert into test values (:v1,:v2) ' using i, i ;
  end loop;
  commit;
end;
--已用时间:  00: 00: 01.01 (硬解析为5秒多)


-查询执行循环插入所生成的parse count (解析数)
select name, value from v$mystat a, v$statname b
where a.STATISTIC#=b.STATISTIC#
and name like 'parse count%';

NAME                                                                  VALUE
---------------------------------------------------------------- ----------
parse count (total)                                                   10206  
parse count (hard)                                                       46  (硬解析46次)
parse count (failures)                                                    0

-- 查询shared_pool的关于执行insert into test语句的cache
select s.SQL_TEXT,s.VERSION_COUNT,s.PARSE_CALLS, s.EXECUTIONS  
from v$sqlarea s where s.SQL_TEXT like '%test%';
--查询结果
insert into test values (:v1,:v2)共执行了10000次软解析。
共执行10206-171 >1000次,原因是还包括其他一些系统表的读写。

http://jj2001hh.blog.163.com/blog/static/615781482008017104824467/

请使用浏览器的分享功能分享到微信等