提到软解析(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/