2014-08-11 Created By BaoXinjian

一、摘要


Oracle硬解析和软解析是我们经常遇到的问题,所以需要考虑何时产生软解析何时产生硬解析,如何判断

1. SQL的执行过程

当发布一条SQL或PL/SQL命令时,Oracle会自动寻找该命令是否存在于共享池中来决定对当前的语句使用硬解析或软解析。

通常情况下,SQL语句的执行过程如下:

Step1. SQL代码的语法(语法的正确性)及语义检查(对象的存在性与权限)。

Step2. 将SQL代码的文本进行哈希得到哈希值。

Step3. 如果共享池中存在相同的哈希值,则对这个命令进一步判断是否进行软解析,否则到e步骤。

Step4. 对于存在相同哈希值的新命令行,其文本将与已存在的命令行的文本逐个进行比较。

这些比较包括大小写,字符串是否一致,空格,注释等,如果一致,则对其进行软解析,转到步骤Step6,无需再次硬解析。

否则到步骤Step5。

Step5. 硬解析,生成执行计划。

Step6. 执行SQL代码,返回结果。

2. Oracle对此sql将进行几个步骤的处理过程:

2.1 解析

Step1:检查共享池中是否有之前解析相同的SQL语句后所存储的SQL文本、解析树和执行计划。

如果能从共享池的缓存库中找到之前解析过生成的执行计划,则SQL语句则不需要再次解析,便可以直接由库缓存得到之前所产生的执行计划,从而直接跳到绑定或执行阶段,这种解析称作软解析。

但是如果在共享池的库缓存中找不到对应的执行计划,则必须继续解析SQL、生成执行计划,这种解析称作硬解析

Step2:语法分析,分析SQL语句的语法是否符合规范,衡量语句中各表达式的意义

Step3:检查是否存在语义错误和权限。语义分析,检查语句中设计的所有数据库对象是否存在,且用户有相应的权限。

Step4:视图转换和表达式转换 将涉及视图的查询语句转换为相应的对基表查询语句。将复杂表达式转化较为简单的等效连接表达式。

Step5:决定最佳执行计划。优化器会生成多个执行计划,在按统计信息带入,找出执行成本最小的执行计划,作为执行此SQL语句的执行计划

Step6:将SQL文本、解析树、执行计划缓存到库缓存,存放地址以及SQL语句的哈希值。

2.2 绑定

如果SQL语句中使用了绑定变量,扫描绑定变量的声明,给绑定变量赋值。则此时将变量值带入执行计划。

2.3 执行

此阶段按照执行计划执行SQL,产生执行结果。不同类型的SQL语句,执行过程也不同。

(1). SELECT查询

检查所需的数据块是否已经在缓冲区缓存中,如果已经在缓冲区缓存中,直接读取器内容即可。

这种读取方式称为逻辑读取。如果所需数据不在缓冲区缓存中,则服务器进程需要先扫描数据块,读取相应数据块到缓冲区缓存,这种读取方式称为物理读。和逻辑读相比较,它更加耗费CPU和IO资源。

(2). 修改操作(INSERT、UPDATE、DELETE)

Step 1:检查所需的数据库是否已经被读取到缓冲区缓存中。如果已经存在缓冲区缓存,则执行Step 3

Step 2:若所需的数据库并不在缓冲区缓存中,则服务器将数据块从数据文件读取到缓冲区缓存中

Step 3:对想要修改的表取得的数据行锁定(Row Exclusive Lock),之后对所需要修改的数据行取得独占锁

Step 4:将撤销数据的Redo记录复制到日志缓冲区,产生数据行的撤销数据,将数据行修改的Redo记录复制到日志缓冲区,修改数据行。

Step 5: 产生数据修改的撤销数据

Step 6:复制数据修改的Redo记录到日志缓冲区

Step 7:修改数据行的内容,如果之前的缓冲为干净缓冲,则此时将变为脏缓冲。

2.4 提取

提取只有SELECT查询语句才有的步骤。获取查询的记录行,必要的时候对查询结果排序。

3. 简而言之

Step1. 语法检查(syntax check)

  检查此sql的拼写是否语法。

Step2. 语义检查(semantic check)

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

Step3、对sql语句进行解析(parse)

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

Step4、执行sql,返回结果(execute and return)

4. 总结

其中,软、硬解析就发生在第三个过程里(对sql语句进行解析parse)。

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

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

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

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

  创建解析树、生成执行计划对于sql的执行来说是开销昂贵的动作,所以,应当极力避免硬解析,尽量使用软解析。

二、软解析


1.下面的三个查询语句,不能使用相同的共享SQL区。尽管查询的表对象使用了大小写,但Oracle为其生成了不同的执行计划

select * from emp;select * from Emp;select * from EMP;

2.类似的情况,下面的查询中,尽管其where子句empno的值不同,Oracle同样为其生成了不同的执行计划

select * from emp where empno=7369select * from emp where empno=7788

3.在判断是否使用硬解析时,所参照的对象及schema应该是相同的,如果对象相同,而schema不同,则需要使用硬解析,生成不同的执行计划

sys@ASMDB> select owner,table_name from dba_tables where table_name like 'TB_OBJ%';OWNER                          TABLE_NAME------------------------------ ------------------------------USR1                           TB_OBJ               --两个对象的名字相同,当所有者不同SCOTT                          TB_OBJ
usr1@ASMDB> select * from tb_obj;scott@ASMDB> select * from tb_obj;      --此时两者都需要使用硬解析以及走不同的执行计划

三、硬解析


硬解析即整个SQL语句的执行需要完完全全的解析,生成执行计划。而硬解析,生成执行计划需要耗用CPU资源,以及SGA资源。在此不得不提的是对库缓存中闩的使用。闩是锁的细化,可以理解为是一种轻量级的串行化设备。当进程申请到闩后,则这些闩用于保护共享内存的数在同一时刻不会被两个以上的进程修改。在硬解析时,需要申请闩的使用,而闩的数量在有限的情况下需要等待。大量的闩的使用由此造成需要使用闩的进程排队越频繁,性能则逾低下。

1. 下面对上面的两种情形进行演示

在两个不同的session中完成,一个为sys帐户的session,一个为scott账户的session,不同的session,其SQL命令行以不同的帐户名开头

如" sys@ASMDB> "  表示使用时sys帐户的session," scott@ASMDB> "表示scott帐户的session

sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;
NAME                      CLASS      VALUE
-------------------- ---------- ----------           --当前的硬解析值为569
parse count (hard)           64        569scott@ASMDB> select * from emp;    sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;      NAME                      CLASS      VALUE-------------------- ---------- ----------           --执行上一个查询后硬解析值为570,解析次数增加了一次parse count (hard)           64        570scott@ASMDB> select * from Emp;sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;        NAME                      CLASS      VALUE-------------------- ---------- ----------           --执行上一个查询后硬解析值为571parse count (hard)           64        571scott@ASMDB> select * from EMP;sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;        NAME                      CLASS      VALUE-------------------- ---------- ----------           --执行上一个查询后硬解析值为572parse count (hard)           64        572   scott@ASMDB> select * from emp where empno=7369;       sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;NAME                      CLASS      VALUE-------------------- ---------- ----------           --执行上一个查询后硬解析值为573parse count (hard)           64        573scott@ASMDB> select * from emp where empno=7788;   --此处原来empno=7369,复制错误所致,现已更正为7788@20130905
sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;NAME                      CLASS      VALUE-------------------- ---------- ----------          --执行上一个查询后硬解析值为574parse count (hard)           64        574

从上面的示例中可以看出,尽管执行的语句存在细微的差别,但Oracle还是为其进行了硬解析,生成了不同的执行计划。即便是同样的SQL语句,而两条语句中空格的多少不一样,Oracle同样会进行硬解析。

四、硬解析改进 - 使用动态语句


1. 更改参数cursor_sharing

参数cursor_sharing决定了何种类型的SQL能够使用相同的SQL area

CURSOR_SHARING = { SIMILAR | EXACT | FORCE }

EXACT      --只有当发布的SQL语句与缓存中的语句完全相同时才用已有的执行计划。

FORCE      --如果SQL语句是字面量,则迫使Optimizer始终使用已有的执行计划,无论已有的执行计划是不是最佳的。

SIMILAR   --如果SQL语句是字面量,则只有当已有的执行计划是最佳时才使用它,如果已有执行计划不是最佳则重新对这个SQL

--语句进行分析来制定最佳执行计划。

可以基于不同的级别来设定该参数,如ALTER SESSION, ALTER SYSTEM

sys@ASMDB> show parameter cursor_shar             --查看参数cursor_sharingNAME                                 TYPE        VALUE------------------------------------ ----------- ------------------------------cursor_sharing                       string      EXACTsys@ASMDB> alter system set cursor_sharing='similar';    --将参数cursor_sharing的值更改为similar

sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;    NAME                      CLASS      VALUE-------------------- ---------- ----------        --当前硬解析的值为865parse count (hard)           64        865scott@ASMDB> select * from dept where deptno=10;sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;  NAME                      CLASS      VALUE-------------------- ---------- ----------        --执行上一条SQL查询后,硬解析的值变为866parse count (hard)           64        866scott@ASMDB> select * from dept where deptno=20;
sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;NAME                      CLASS      VALUE-------------------- ---------- ----------        --执行上一条SQL查询后,硬解析的值没有发生变化还是866parse count (hard)           64        866sys@ASMDB> select sql_text,child_number from v$sql   -- 在下面的结果中可以看到SQL_TEXT列中使用了绑定变量:"SYS_B_0" 2  where sql_text like 'select * from dept where deptno%';SQL_TEXT                                           CHILD_NUMBE-------------------------------------------------- ------------  select * from dept where deptno=:"SYS_B_0"                    0sys@ASMDB> alter system set cursor_sharing='exact';       --将cursor_sharing改回为exact--接下来在scott的session 中执行deptno=40 和的查询后再查看sql_text,当cursor_sharing改为exact后,每执行那个一次--也会在v$sql中增加一条语句

sys@ASMDB> select sql_text,child_number from v$sql                2  where sql_text like 'select * from dept where deptno%';SQL_TEXT                                           CHILD_NUMBER-------------------------------------------------- ------------select * from dept where deptno=50                            0      select * from dept where deptno=40                            0select * from dept where deptno=:"SYS_B_0"                    0

2. 使用绑定变量的方式

绑定变量要求变量名称,数据类型以及长度是一致,否则无法使用软解析

(1). 绑定变量(bind variable)是指在DML语句中使用一个占位符,即使用冒号后面紧跟变量名的形式,如下

select * from emp where empno=7788    --未使用绑定变量

select * from emp where empono=:eno   --:eno即为绑定变量

在第二个查询中,变量值在查询执行时被提供。该查询只编译一次,随后会把查询计划存储在一个共享池(库缓存)中,以便以后获取和重用这个查询计划。

(2). 下面使用了绑定变量,但两个变量其实质是不相同的,对这种情形,同样使用硬解析

select * from emp where empno=:eno;

select * from emp where empno=:emp_no

使用绑定变量时要求不同的会话中使用了相同的回话环境,以及优化器的规则等

scott@ASMDB> create table tb_test(col int);     --创建表tb_test

scott@ASMDB> create or replace procedure proc1  --创建存储过程proc1使用绑定变量来插入新记录2  as3  begin4      for i in 1..100005      loop6          execute immediate 'insert into tb_test values(:n)' using i;7      end loop;8  end;9  /
Procedure created.scott@ASMDB> create or replace procedure proc2 --创建存储过程proc2,未使用绑定变量,因此每一个SQL插入语句都会硬解析2  as3  begin4      for i in 1..100005      loop6          execute immediate 'insert into tb_test values('||i||')';7      end loop;8  end;9  /Procedure created.scott@ASMDB> exec runstats_pkg.rs_startPL/SQL procedure successfully completed.scott@ASMDB> exec proc1;PL/SQL procedure successfully completed.scott@ASMDB> exec runstats_pkg.rs_middle;PL/SQL procedure successfully completed.scott@ASMDB> exec proc2;PL/SQL procedure successfully completed.scott@ASMDB> exec runstats_pkg.rs_stop(1000);Run1 ran in 1769 hsecsRun2 ran in 12243 hsecs             --run2运行的时间是run1的/1769≈倍run 1 ran in 14.45% of the time   Name                                Run1      Run2      DiffLATCH.SQL memory manager worka       410     2,694     2,284LATCH.session allocation             532     8,912     8,380LATCH.simulator lru latch             33     9,371     9,338LATCH.simulator hash latch            51     9,398     9,347STAT...enqueue requests               31    10,030     9,999STAT...enqueue releases               29    10,030    10,001STAT...parse count (hard)              4    10,011    10,007    --硬解析的次数,前者只有四次STAT...calls to get snapshot s        55    10,087    10,032STAT...parse count (total)            33    10,067    10,034STAT...consistent gets               247    10,353    10,106STAT...consistent gets from ca       247    10,353    10,106STAT...recursive calls            10,474    20,885    10,411STAT...db block gets from cach    10,408    30,371    19,963STAT...db block gets              10,408    30,371    19,963LATCH.enqueues                       322    21,820    21,498    --闩的队列数比较LATCH.enqueue hash chains            351    21,904    21,553STAT...session logical reads      10,655    40,724    30,069LATCH.library cache pin           40,348    72,410    32,062    --库缓存pinLATCH.kks stats                        8    40,061    40,053LATCH.library cache lock             318    61,294    60,976LATCH.cache buffers chains        51,851   118,340    66,489LATCH.row cache objects              351   123,512   123,161LATCH.library cache               40,710   234,653   193,943LATCH.shared pool                 20,357   243,376   223,019Run1 latches total versus runs -- difference and pctRun1      Run2      Diff     Pct157,159   974,086   816,927  16.13%          --proc2使用闩的数量也远远多于proc1,其比值是.13%  

PL/SQL procedure successfully completed.

(3). 使用绑定变量的好处

  • 由上面的示例可知,在未使用绑定变量的情形下,不论是解析次数,闩使用的数量,队列,分配的内存,库缓存,行缓存远远高于绑定
  • 变量的情况。因此尽可能的使用绑定变量避免硬解析产生所需的额外的系统资源。
  • 绑定变量的优点
  • 减少SQL语句的硬解析,从而减少因硬解析产生的额外开销(CPU,Shared pool,latch)。其次提高编程效率,减少数据库的访问次数。
  • 绑定变量的缺点
  • 优化器就会忽略直方图的信息,在生成执行计划的时候可能不够优化。SQL优化相对比较困难

五、总结


1.尽可能的避免硬解析,因为硬解析需要更多的CPU资源,闩等。

2.cursor_sharing参数应权衡利弊,需要考虑使用similar与force带来的影响。

3.尽可能的使用绑定变量来避免硬解析。

Thanks and Regards

参考:乐沙弥大神 http://blog.csdn.net/leshami/article/details/6195483

参考:乐沙弥大神 http://10.61.208.50:15871/cgi-bin/blockpage.cgi?ws-session=18446744072512592920

参考:乐沙弥大神 http://czmmiao.iteye.com/category/143940

参考:潇湘隐者 http://www.cnblogs.com/kerrycode/p/3356845.html

PLSQL_解析过程及硬解析和软解析的区别(案例)相关推荐

  1. android播放器和视频拍摄中的硬解和软解以及硬编和软编的区别

    转载 原文地址:https://blog.csdn.net/ltym2014/article/details/82354606 https://blog.csdn.net/lipengshiwo/ar ...

  2. 视频解码硬解和软解的区别及如何选择

    视频解码硬解和软解的区别及如何选择 硬解 字面上理解就是用硬件解码.通过显卡的视频加速功能对高清视频进行解码.可以理解为有一个专门的电路板来进行视频的解码工作,是依靠GPU. 调用GPU的专门模块编码 ...

  3. “硬解码”与“软解码”的区别

    关于"硬解码"与"软解码" 忧蓝 发布于: 2010-08-02 11:03 由于高清视频的分辨率远远高于一般格式视频,使得高清视频的码率非常高.再加上VC-1 ...

  4. 硬编码和软编码的区别

    Android 视频 硬编码和软编码的区别 软编码和硬编码如何区分 软编码:使用CPU进行编码 硬编码:使用非CPU进行编码,如显卡GPU.专用的DSP.FPGA.ASIC芯片等 软编码和硬编码比较 ...

  5. SpringMVC_视图解析(解析过程、视图、常见视图解析器、重定向)

    今天来说说SpringMVC视图是怎么解析的. 1.SpringMVC如何解析视图概述 1.1.无论控制器返回一个String,ModelAndView,View都会转换为ModelAndView对象 ...

  6. 硬解码和软解码的区别

    我们在计算机上播放的视频文件都是经过压缩的,因为这样有利于节约存储空间:那么在播放过程,就需要进行一个反射的解压缩过程.在以前这项工作都是由CPU来完成的,对于普通分辨率的AVI.RMVB等文件,绝大 ...

  7. 手机视频硬解码和软解码的区别

    在手机评测视频播放能力的时候经常会提到"硬解码"和"软解码",但是很多人不太明白是什么意思,其实问题很简单.大家都知道PC都有CPU和GPU(显卡),在手机上也 ...

  8. 硬断点和软断点的区别

    硬断点--break point 软断点--assert 简单的解释: 硬件断点:硬断点需要硬件寄存器提供支持,断点的数目受Embedded ICE中的Watchpoint数目的限制,但是可以在任何地 ...

  9. [转]video视频解码硬解和软解的区别及如何选择

    如果你认为本系列文章对你有所帮助,请大家有钱的捧个钱场,点击此处赞助,赞助额0.1元起步,多少随意 声明:本文只用于个人学习交流,若不慎造成侵权,请及时联系我,立即予以改正 锋影 email:1741 ...

最新文章

  1. 用C#和本地Windows API操纵系统菜单
  2. matlab消去前一个图,各位matlab高手,如何从2个3元方程中消去一个变量,然后做3维图形~...
  3. php获取总共内存_php获取页面运行使用内存的两个函数
  4. metasploit framework
  5. 固定UILabel宽度分行显示
  6. 安川伺服总线通讯方式_MⅢ总线特点 安川伺服选型与应用案例
  7. Hexo 入门指南(五) - 搬家 备份
  8. 【Elasticsearch】Elasticsearch 悬空索引
  9. SAP License:SAP集成(后面为粘贴)
  10. 每周送新书:Android软件安全、深入浅出Istio、软件架构设计
  11. python3 与python2 异常处理的区别与联系
  12. python正则表达式基础
  13. 计算机动漫与游戏制作心得,学习课件制作的心得体会(精选10篇)
  14. 如何用运营思维,搭建会员运营体系
  15. 利用java制作桌面应用程序_Java桌面应用
  16. 在线小蝌蚪匿名聊天室源码 用于网站引流
  17. Windows应急响应排查
  18. 一个可以把单张静态照片转化成 3D 图片的AI 工具
  19. 卸载编译安装的mysql
  20. 2021年全球渗膜式空气干燥器收入大约525百万美元,预计2028年达到580百万美元

热门文章

  1. 万维网源代码正在被发明人拍卖,有人出价1800万,还在不断上涨
  2. @老板:别开视频会议了,效率低没人care,斯坦福、微软都可以作证
  3. 有人做出了中文版GPT-2,可用于写小说、诗歌、新闻等;15亿参数版GPT-2被两名研究生复现...
  4. OpenGL学习(4)——纹理(补)
  5. 如何让自己的开源库支持cocoapods?
  6. Windows 7安装MySQL最后一步提示错误“mysql 终结点映射器中没有更多的终结点可用的” 解决方法...
  7. JAVA (集合和数据结构)
  8. 查看Unix/Linux的CPU个数和内存大小,系统位数(转载)
  9. 英特尔未来教育核心课程
  10. git 操作命令整理