一条SQL的执行过程
1.在PGA中进行语法、语义检查(检查执行该SQL语句的用户是否有权限访问某个对象)
2.检查该SQL是否存在于共享池
3.如果SQL语句不存在就对该SQL进行硬解析,生成执行计划,解析树等等,如果SQL语句存在,就选择最佳执行计划,这个就是软解析
4.执行SQL,返回结果
主要讨论一下oracle的解析方式
1硬解析:SQL转换为HASH_VALUE在shared_pool没找到匹配值
2软解析:省略生成执行计划,解析树等步骤
3软软解析:当执行SQL时,首先要打开游标,执行完成后,要关闭游标,游标可以理解为SQL语句的一个句柄。在执行软软解析之前,首先要进行软解析,MOS上说执行3次的SQL语句会把游标缓存到PGA,当再有相同的SQL执行时,如果游标是关闭的,则打开游标,跳过解析的所有过程直接去取执行计划。
4不解析:执行3次的SQL语句会把游标缓存到PGA,当再有相同的SQL执行时,如果游标是打开的,跳过解析的所有过程直接去取执行计划。(与软软解析区别只在于是否打开游标),可以参考v$open_cursor视图
实验:
硬解析
alter system flush shared_pool;
SCOTT@ fyl>select * from emp where empno=1;
SCOTT@ fyl>select * from emp where empno=2;
SCOTT@ fyl>select * from emp where empno=3;
软解析
SCOTT@ fyl>var eno number
SCOTT@ fyl>exec :eno :=1;
SCOTT@ fyl>select * from emp where empno=:eno;
SCOTT@ fyl>exec :eno :=2;
SCOTT@ fyl>select * from emp where empno=:eno;
SCOTT@ fyl>exec :eno :=3;
SCOTT@ fyl>select * from emp where empno=:eno;
不解析
SCOTT@ fyl>declare
2 p_emp emp%rowtype;
3 begin
4 for i in 1 .. 20 loop
5 execute immediate 'select * from emp where empno=7788' into p_emp;
6 end loop;
7 end;
8 /
SCOTT@ fyl>select hash_value,sql_text,parse_calls,loads, EXECUTIONS from v$sql where sql_text like 'select * from emp%';
HASH_VALUE SQL_TEXT PARSE_CALLS LOADS EXECUTIONS
---------- ------------------------------------------------------------ ----------- ---------- ----------
3923248223 select * from emp where empno=2 1 1 1 --硬解析
1410730372 select * from emp where empno=1 1 1 1 --硬解析
2367053566 select * from emp where empno=:eno 3 1 3 --软解析
3663109429 select * from emp where empno=3 1 1 1 --硬解析
1075160986 select * from emp where empno=7788 1 1 20 --不解析
EXECUTIONS:SQL执行次数
LOADS:硬解析次数
PARSE_CALLS:软解析次数