ORACLE硬解析分析

  • 前言
  • ORACLE的硬解析和软解析
  • AWR报告中的硬解析
  • 通过ORACLE视图判断硬解析
  • 关于version count


前言

工作中ORACLE使用的越多,发现对ORACLE了解的越少。用到现在发现对于ORACLE什么都不会了。悲剧。今天看AWR报告的时候看到了硬解析,顺便就把相关的知识点重新学习了一遍。

ORACLE的硬解析和软解析

在ORACLE中,当执行一条新的SQL时,大致步骤如下:
1、语法检查,如果有错误的SQL就不会执行后续的步骤
2、语义和权限检查,比如检查SQL中的对象(表、视图等)是否存在,当前用户对SQL是否有执行权限
3、ORACLE内部对SQL执行解析和优化
4、根据统计信息生成执行计划。这句话其实也解决了我之前一些疑惑,在这篇博文里先不多讨论
5、将游标信息保存到库缓存
6、执行SQL并返回执行结果
这其实就是一个硬解析的过程,原因很简单,“执行一条新的SQL”,必然是硬解析。其中对SQL进行解析和生成执行计划是最耗时的步骤,但是我自己没有验证,参考官方文档和网上的资料。
软解析,其实就是跳过了SQL解析和生成执行计划的步骤
误区一:只要出现硬解析就是程序问题。这个未必,ORACLE11g的版本有一个BUG,它会导致一些本来可以做软解析的SQL却执行了硬解析,BUG号如下:

Bug:9689310:

  • Non sharability of cursors due to BIND_MISMATCH.
    Bug:6981690:
  • Non sharability of cursors due to PQ_SLAVE_MISMATCH
    Bug:8981059:
  • Non sharability of cursors due to USER_BIND_PEEK_MISMATCH.

在https://support.oracle.com/portal/上可以查询对应BUG所存在的版本。
误区二:只要使用了绑定变量,就一定不会硬解析。这个也未必,导致硬解析的问题很多,看v$sql_shared_cursor视图就知道,这个视图里每一列都代表了一个导致硬解析的原因。所以,解决硬解析的主要手段是使用绑定变量,但是使用了绑定变量未必一定就是软解析。

AWR报告中的硬解析

涉及到生产环境,无法把完整的AWR报告发上来,只能发处理后的截图,大家见谅

postgresql 硬解析和软解析 oracle 硬解析_postgresql 硬解析和软解析


AWR报告中显示hard parses每秒18.7个,有资料说这个值不不能超过20,我觉得这个标准没有那么硬性,例如我的AWR报告间隔时间是7天,那每秒18.7次硬解析的话还是比较恐怖的。只是服务器的配置够牛X,所以DB TIME看着很正常。服务器的牛逼不能作为SQL不优化的理由

通过ORACLE视图判断硬解析

AWR报告中只能看到硬解析的情况,但是看不到硬解析的语句,因此要用v$sqlarea和v$sql_shared_cursor来判断。
首先执行如下语句,过滤出解析次数明显偏高的SQL:

SELECT S.SQL_ID, S.SQL_FULLTEXT,S.VERSION_COUNT ,S.LAST_LOAD_TIME FROM  v$sqlarea  S ORDER BY S.VERSION_COUNT DESC;

抱歉因为是生产环境就不放截图了。查询结果中会有四列,分别是SQL_ID, SQL_FULLTEXT, VERSION_COUNT, LAST_LOAD_TIME,其中VERSION_COUNT就是解析的次数。注意出现多次解析未必就是硬解析,从查询结果中找到对应的SQL_ID,然后用如下的SQL查询:

SELECT * FROM v$sql_shared_cursor c where c.sql_id = '[SQL_ID]'

v$sql_shared_cursor视图中可以看到硬解析的原因,该视图中从第四列到最后一列,每一列都代表一类导致硬解析的原因,值有Y|N,如果是Y,就说明该列所对应的原因导致了硬解析,例如在查询结果中如果BIND_EQUIV_FAILURE的值是Y,原因就是BIND_EQUIV_FAILURE,那就可以确定这个SQL肯定是硬解析,如果解析次数很多,但是这个查询结果都是N,那么它查询次数多的原因就不是硬解析,可能是别的原因。,如果大家觉得我的这个观点不正确,欢迎留言指正,这样的列一共有320列,也就是在ORACLE中会有320种原因导致硬解析,我仔细看了一下这320列,最后发现我一列都看不懂。。。嗯……GOOD。所以才有我开头所说的,用ORACLE的时间越长,发现自己懂的越少。

硬解析具体的原因以我现在的水平也无法做到很详细的解释,以后在不断补充吧。网上有很多从ORACLE官网摘抄过来的表格,但是没有做进一步的解释和分析,这个表格我就不抄了。

关于version count

当SQL 语句第一次执行时,在硬解析时,会创建parent cursor 和child cursor。 这2个是必须的。这2个过程是比较费资源的。也是硬解析里主要做的事。 当再次执行这个SQL时,Oracle 会先对SQL 语句进行hash 运算,产生一个hash 值,然后用这个HASH 值到buckets里去查找,hash value 存放在parent cursor里。 如果找到了,就去检查child cursor。 如果可以重用这个child cursor,那么就直接调用cursor里的执行计划。 如果不可重用,就会创建一个新的child cursor。 这个child cursor 的个数,就是version count。 不同parent cursor 对应的child cursor 越多,version count 就越高