转载:http://blog.csdn.net/zftang/article/details/6319332

提到软解析(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的执行来说是开销昂贵的动作,所以,应当极力避免硬解析,尽量使用软解析。
这就是在很多项目中,倡导开发设计人员对功能相同的代码要努力保持代码的一致性,以及要在程序中多使用绑定变量的原因。

Oracle中的SQL在执行之前进行解析,一个硬解析包括下面的步骤:

1. 加载到共享池中 - SQL源代码被加载到内存中。 
   2. 语法解析 - Oracle检查语法拼写错误。 
   3. 语义解析 - Oracle验证来自数据字典的所有表名和列名并且验证你是否有权访问这些数据。 
   4. 查询转换 - 如果允许(query_rewrite=true),oracle将把复杂的SQL转换为等价的简单形式。 
   5. 优化 - 根据模式的统计信息创建执行计划(在10g中或许会使用动态的样本统计信息)。 
   6. 创建可执行文件 - Oracle创建一个服务于SQL查询的、调用本地文件的可执行文件。

Oracle提供了 shared_pool_size参数来缓存SQL从而使我们不需要重复解析SQL。但是,如果shared_pool_size设置太小或者在代码中使用了非重用的SQL(例如包含直接量where name="fred"),SQL语句可能会过期。

在Oracle中软解析和硬解析的区别是什么?仅仅是上面用红色标明的第一步。也就是说,软解析不需要重新装载到共享池(以及相关的内存分配)。

通常很高的解析调用次数(>10/秒)表明你的系统有大量不同的SQL语句,或者你的SQL语句没有被重用(例如,没有使用绑定变量)。

硬解析需要把 SQL语句加载到共享池中。硬解析比软解析差很多,因为它牵涉到共享池中内存的分配和管理。一旦被加载,SQL必须完全重新检查语法和语义以及生成可执行目标。

如果shared_pool_size设置的太小或者SQL语句没有重用,则会发生大量的硬解析。

所以要适当的设置共享池大小并且通过主机变量重用SQL。

软解析、硬解析的一个小测试:
SQL> create global temporary table sess_event on commit preserve rows as select * from v$session_event where 1=0;

Table created

SQL> insert into sess_event
2 select * from v$session_event
3 where sid=(select sid from v$mystat where rownum=1);

9 rows inserted

SQL> 
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
2 AND NAME LIKE 'parse count%'
3 ;

NAME VALUE
---------------------------------------------------------------- ----------
parse count (total) 32127
parse count (hard) 30365
parse count (failures) 1

SQL> 
SQL> begin
2 for i in 1..10000 loop
3 execute immediate 'insert into test values('||i||','||i||')';
4 end loop;
5 commit;
6 end;
7 /

PL/SQL procedure successfully completed

SQL> 
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
2 AND NAME LIKE 'parse count%';

NAME VALUE
---------------------------------------------------------------- ----------
parse count (total) 42201
parse count (hard) 40379
parse count (failures) 1
没有使用绑定变量(这种写法往往有人误认为使用了绑定,这里就不多解释了)总解析次数:10074
硬解析次数:10014
上边2个值除了我们的循环10000次外,还包括其他一些系统表的读写,所以解析次数大于10000,但是我们要注意下面的结果,对于每个SQL
都有一个版本,也就是ORACLE对于每个不同的SQL分别执行了硬解析,下面是共享池最后缓存的数据(部分已经被覆盖)

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
insert into test values(9630,9630) 1 1 1
insert into test values(9950,9950) 1 1 1
insert into test values(9625,9625) 1 1 1
insert into test values(9592,9592) 1 1 1
insert into test values(9940,9940) 1 1 1
insert into test values(9897,9897) 1 1 1
insert into test values(9679,9679) 1 1 1
insert into test values(9850,9850) 1 1 1
insert into test values(9744,9744) 1 1 1
insert into test values(9938,9938) 1 1 1
insert into test values(9977,9977) 1 1 1
insert into test values(9907,9907) 1 1 1
insert into test values(9809,9809) 1 1 1
insert into test values(9800,9800) 1 1 1
insert into test values(9645,9645) 1 1 1
insert into test values(9724,9724) 1 1 1
insert into test values(9799,9799) 1 1 1
insert into test values(9818,9818) 1 1 1
insert into test values(9642,9642) 1 1 1
insert into test values(9624,9624) 1 1 1

中间内容略

SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
insert into test values(9838,9838) 1 1 1
insert into test values(9716,9716) 1 1 1
insert into test values(9691,9691) 1 1 1
insert into test values(9831,9831) 1 1 1
insert into test values(×××,×××) 1 1 1
insert into test values(9883,9883) 1 1 1
insert into test values(9865,9865) 1 1 1
insert into test values(9901,9901) 1 1 1
insert into test values(9657,9657) 1 1 1
insert into test values(10000,10000) 1 1 1
insert into test values(9659,9659) 1 1 1
insert into test values(9746,9746) 1 1 1
insert into test values(9695,9695) 1 1 1
insert into test values(9869,9869) 1 1 1
insert into test values(9804,9804) 1 1 1
insert into test values(9843,9843) 1 1 1

435 rows selected

SQL> truncate talbe sess_event;

truncate talbe sess_event

ORA-03290: 无效的截断命令 - 缺失 CLUSTER 或 TABLE 关键字

SQL> truncate table sess_event;

Table truncated

SQL> alter system flush shared_pool;

System altered

SQL> 
SQL> insert into sess_event
2 select * from v$session_event
3 where sid=(select sid from v$mystat where rownum=1);

10 rows inserted

SQL> 
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
2 AND NAME LIKE 'parse count%';

NAME VALUE
---------------------------------------------------------------- ----------
parse count (total) 42643
parse count (hard) 40456
parse count (failures) 2

SQL> 
SQL> begin
2 for i in 1..10000 loop
3 execute immediate 'insert into test values(:v1,:v2)' using i,i;
4 end loop;
5 commit;
6 end;
7 /

PL/SQL procedure successfully completed

SQL> 
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
2 AND NAME LIKE 'parse count%';

NAME VALUE
---------------------------------------------------------------- ----------
parse count (total) 42688
parse count (hard) 40466
parse count (failures) 2
下面看下使用绑定变量的情况(真正使用了绑定)总解析次数:45
硬解析次数:10
我们可以看出差异是多么大了,呵呵,对于SQL本身只有一次软解析,执行次数为10000

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
begin for i in 1..10000 loop execute immediate 'insert into test values(:v1,:v2 1 1 1
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2, next_dat 1 1 1
insert into test values(:v1,:v2) 1 1 10000
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 1 1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 1 1

SQL> alter system flush shared_pool;

System altered
但是我们要注意一个情况,即时同样的SQL如果没有使用绑定变量,ORACLE也会对其执行一次软解析的,但是没有硬解析,如下:
每执行一次SQL,也会同时产生其他写系统表等很多相关的软解析包括查询SQL本身。硬解析不变。
SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2, next_dat 1 1 1
insert into test values('1','1111111111') 1 1 1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 1 1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 1 1

SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2, next_dat 1 1 1
insert into test values('1','1111111111') 1 2 2
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 1 1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 2 2

SQL>

SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
2 AND NAME LIKE 'parse count%';

NAME VALUE
---------------------------------------------------------------- ----------
parse count (total) 42906
parse count (hard) 40520
parse count (failures) 2

SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
begin dbsnmp.mgmt_response.get_latest_curs(:a); end; 1 1 1
/* OracleOEM */ BEGIN IF (:1 = 'READ WRITE') THEN ---- -- For a read- 1 1 1
/* OracleOEM */ DECLARE instance_number NUMBER; latest_task_id NUMBER; 1 1 1
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2, next_dat 1 4 4
insert into test values('1','1111111111') 1 3 3
DELETE FROM MGMT_DB_LATEST_HDM_FINDINGS WHERE TARGET_GUID = :B2 AND COLLECTION_T 2 3 3
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 1 1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 3 3

8 rows selected

SQL> 
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
2 AND NAME LIKE 'parse count%';

NAME VALUE
---------------------------------------------------------------- ----------
parse count (total) 42922
parse count (hard) 40520
parse count (failures) 2

SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> insert into test values('1','1111111111');

1 row inserted

SQL> commit;

Commit complete

SQL> select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper(sql_text) like '%TEST%';

SQL_TEXT VERSION_COUNT PARSE_CALLS EXECUTIONS
-------------------------------------------------------------------------------- ------------- ----------- ----------
begin dbsnmp.mgmt_response.get_latest_curs(:a); end; 1 1 1
/* OracleOEM */ BEGIN IF (:1 = 'READ WRITE') THEN ---- -- For a read- 1 1 1
/* OracleOEM */ DECLARE instance_number NUMBER; latest_task_id NUMBER; 1 1 1
update sys.job$ set failures=0, this_date=null, flag=:1, last_date=:2, next_dat 1 5 5
insert into test values('1','1111111111') 1 5 5
DELETE FROM MGMT_DB_LATEST_HDM_FINDINGS WHERE TARGET_GUID = :B2 AND COLLECTION_T 2 3 3
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 1 1
select SQL_TEXT,VERSION_COUNT,PARSE_CALLS,EXECUTIONS from v$sqlarea where upper( 1 4 4

8 rows selected

SQL> 
SQL> SELECT NAME,VALUE FROM V$MYSTAT A,V$STATNAME B WHERE A.STATISTIC#=B.STATISTIC#
2 AND NAME LIKE 'parse count%';

NAME VALUE
---------------------------------------------------------------- ----------
parse count (total) 42946
parse count (hard) 40520
parse count (failures) 2

SQL>

通过这个例子我们也就知道V$SQLAREA中的解析包含什么内容了。

转载于:https://blog.51cto.com/1406339/1348904

oracle硬解析和软解析相关推荐

  1. Oracle sql解析类型, 软解析和硬解析浅析

    这篇文章是参考加甲骨论老相老师视频所做的学习笔记: http://www.jiagulun.com/thread-2675-1-1.html Sql 执行的流程分成3部分: 解析部分(Parse): ...

  2. 【Oracle】硬解析、软解析和软软解析

    [Oracle]硬解析.软解析和软软解析 前言   在 Oracle 中,每条 SQL 语句在执行之前都需要经过解析(Parse),根据解析的过程可以分为 3 种类型:硬解析(Hard Parse). ...

  3. Oracle硬解析,软解析,软软解析介绍

    Oracle数据库中的CURSOR分为两种类型:Shared Cursor 和 Session Cursor 1,Shared Cursor Oracle里的第一种类型的Cursor就是Shared ...

  4. 详解ORACLE数据库硬解析、软解析、软软解析

    概述 TOM大叔的调优书中说过一句话,大概意思就是:如果有人让我写本怎样让ORACLE性能最慢的书的话我会将取消绑定变量(bind variable)做为书的第一章和最后一章,可见绑定变量的重要性.而 ...

  5. Oracle进阶学习3:SQL语句解析类型——硬解析和软解析

    文章目录 硬解析和软解析 shared pool功能 shared pool组成 SQL语句 硬解析和软解析 Oracle数据信息全部存储在数据字典中, Oracle的解析有两种,软解析以及硬解析 硬 ...

  6. 彻底弄懂oracle硬解析、软解析、软软解析

    硬解析和软解析有相同的一步,而软软解析与硬解析.软解析完全不一样.先来说下理论上的东西,然后来做个实验. 硬解析过程: 1.语法.语义及权限检查: 2.查询转换(通过应用各种不同的转换技巧,会生成语义 ...

  7. mysql 硬解析 软解析_ORACLE sql语句的硬解析与软解析(收藏)

    我们都知道在Oracle中每条SQL语句在执行之前都需要经过解析,这里面又分为软解析和硬解析.那么这两种解析有何不同之处呢?它们又分别是如何进行解析呢?Oracle内部解析的步骤又是如何进行的呢?下面 ...

  8. PLSQL_解析过程及硬解析和软解析的区别(案例)

    2014-08-11 Created By BaoXinjian 一.摘要 Oracle硬解析和软解析是我们经常遇到的问题,所以需要考虑何时产生软解析何时产生硬解析,如何判断 1. SQL的执行过程 ...

  9. SQL解析之硬解析和软解析

    当客户端进程,将SQL语句通过监听器发送到Oracle时, 会触发一个Server process生成,来对该客户进程服务.Server process得到SQL语句之后,对SQL语句进行Hash运算 ...

  10. mysql硬解析与软解析_SQL 软解析和硬解析详解

    当客户端进程,将SQL语句通过监听器发送到Oracle时, 会触发一个Server process生成,来对该客户进程服务.Server process得到SQL语句之后,对SQL语句进行Hash运算 ...

最新文章

  1. Cannot resolve method ‘call(java.lang.String, org.apache.flink.table.api.ApiExpression)‘
  2. 计组学习笔记(一):浮点数的表示和运算
  3. ISO8583报文协议(转)
  4. python数据可视化编程实战 第2版 github_Python数据可视化编程实战(三):在Mac OS X上安装matplotlib...
  5. php微信显示通讯录,微信小程序通讯录功能实现思路分享
  6. springboot集成ureport2
  7. 怎么写化学反应方程式?
  8. COOL EDIT PRO 消原声
  9. 营销理论模型:4P、STP理论、SWOT图解
  10. python正态性检验_在python中做正态性检验示例
  11. 动力电池集成关键技术及电池测试与验证
  12. 计算机网络安全基础知识复习
  13. php身份证实名认证接口
  14. ValueError: continuous format is not supported
  15. 一文看尽 CVPR 2022 最新 20 篇 Oral 论文
  16. cdh6.1,cdh6.2 hue sqoop组件提交异常
  17. matlab寻峰算法,求助我这个寻峰算法该怎么提高灵敏度
  18. 幼儿园手工之自制时钟_「时钟手工」幼儿园玩教具手工时钟,培养孩子的时间观念...
  19. 转载自科技猿人:联想5G投票这事,我们就来彻底讲清楚
  20. 智能时代为什么需要区块链技术?

热门文章

  1. C语言函数指针简单应用
  2. 使用javascript 实现.net 验证控件功能
  3. 删除百度贴吧上的内容
  4. iOS/Android React Native 配置教程
  5. ES6中的const命令【转】
  6. 学习笔记:利用GeoServer结合uDig发布WMS详细过程
  7. windows定时自动运行R脚本的正确姿势
  8. R与Python手牵手:特征工程(数值型变换)
  9. 在 Ubuntu 18.04 上安装 Python 3.7
  10. .编写一个文件加解密程序,通过命令行完成加解 密工作