如果应用程序发出一条语句,并且Oracle数据库无法重用游标,则它必须构建该应用程序代码的新的可执行版本。此操作称为硬解析。
软解析是任何解析不是硬解析,并发生在数据库可以重用现有的代码。一些软解析比其他软解析占用更少的资源。例如,如果该语句的父游标已经存在,则Oracle数据库可以执行各种优化,然后将子游标存储在共享SQL区域中。但是,如果不存在父游标,则Oracle数据库还必须将父游标存储在共享SQL区域中,这会产生额外的内存开销。
有效地,硬解析会在运行语句之前重新编译它。在每次执行之前硬解析SQL语句类似于在每次执行之前重新编译C程序。
硬解析执行以下操作:
- 检查SQL语句的语法
- 检查SQL语句的语义
- 检查发出该语句的用户的访问权限
- 制定执行计划
- 多次访问库高速缓存和数据字典高速缓存以检查数据字典
硬解析的一个特别耗费资源的方面是多次访问库高速缓存和数据字典高速缓存以检查数据字典。当数据库访问这些区域时,它将在所需对象上使用称为锁存器的序列化设备,以使它们的定义在检查期间不会更改。闩锁争用会增加语句执行时间并减少并发性。
由于上述所有原因,硬解析的CPU和内存开销可能会导致严重的性能问题。该问题在Web应用程序中尤其明显,该Web应用程序接受来自表单的用户输入,然后动态生成SQL语句。真实世界性能小组强烈建议尽可能减少硬解析。
视频:
示例20-4使用V $ SQL查找解析信息
您可以使用各种技术来监视硬解析和软解析。本示例查询会话统计信息,以确定重复执行DBA_JOBS查询是否会增加硬解析计数。语句的第一次执行将硬解析计数增加到49,但是第二次执行不改变硬解析计数,这意味着Oracle数据库重用了应用程序代码。
SQL> ALTER SYSTEM FLUSH SHARED_POOL;
System altered.
SQL> COL NAME FORMAT a18
SQL> SELECT s.NAME, m.VALUE
2 FROM V$STATNAME s, V$MYSTAT m
3 WHERE s.STATISTIC# = m.STATISTIC#
4 AND s.NAME LIKE '%(hard%';
NAME VALUE
------------------ ----------
parse count (hard) 48
SQL> SELECT COUNT(*) FROM DBA_JOBS;
COUNT(*)
----------
0
SQL> SELECT s.NAME, m.VALUE
2 FROM V$STATNAME s, V$MYSTAT m
3 WHERE s.STATISTIC# = m.STATISTIC#
4 AND s.NAME LIKE '%(hard%';
NAME VALUE
------------------ ----------
parse count (hard) 49
SQL> SELECT COUNT(*) FROM DBA_JOBS;
COUNT(*)
----------
0
SQL> SELECT s.NAME, m.VALUE
2 FROM V$STATNAME s, V$MYSTAT m
3 WHERE s.STATISTIC# = m.STATISTIC#
4 AND s.NAME LIKE '%(hard%';
NAME VALUE
------------------ ----------
parse count (hard) 49
示例20-5使用跟踪文件查找解析信息
本示例使用SQL Trace和TKPROF实用程序来查找解析信息。您以管理员权限登录数据库,然后查询跟踪文件的目录位置(包括示例输出):
SET LINESIZE 120
COLUMN value FORMAT A80
SELECT value
FROM v$diag_info
WHERE name = 'Default Trace File';
VALUE
--------------------------------------------------------------------------------
/disk1/oracle/log/diag/rdbms/orcl/orcl/trace/orcl_ora_23054.trc
启用跟踪,使用TRACEFILE_IDENTIFIER初始化参数为跟踪文件指定一个有意义的名称,然后查询hr.employees:
EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE(waits=>TRUE, binds=>TRUE);
ALTER SESSION SET TRACEFILE_IDENTIFIER = "emp_stmt";
SELECT * FROM hr.employees;
EXIT;在默认跟踪文件目录中搜索生成的跟踪文件:
% ls *emp_stmt.trc
orcl_ora_17950_emp_stmt.trc
使用TKPROF格式化跟踪文件,然后打开格式化的文件:
% tkprof orcl_ora_17950_emp_stmt.trc emp.out; vi emp.out格式化的跟踪文件包含用于查询的解析信息hr.employees。
SQL ID: brmjpfs7dcnub Plan Hash: 1445457117
SELECT *
FROM
hr.employees
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.07 0.08 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 9 0.00 0.00 3 12 0 107
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 11 0.07 0.08 3 12 0 107
Misses in library cache during parse: 1 --没有命令为1 为硬解析
Optimizer mode: ALL_ROWS
Parsing user id: SYSTEM
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
107 107 107 TABLE ACCESS FULL EMPLOYEES (cr=12 pr=3 pw=0 time=497
us starts=1 cost=2 size=7383 card=107)
库高速缓存未命中表示硬解析。为再次执行同一条语句执行相同的步骤将产生以下跟踪输出,该跟踪输出显示没有库高速缓存未命中:
SQL ID: brmjpfs7dcnub Plan Hash: 1445457117
SELECT *
FROM
hr.employees
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 9 0.00 0.00 3 12 0 107
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 11 0.00 0.00 3 12 0 107
Misses in library cache during parse: 0 ----解析期间库高速缓存中未命中 为0 即为命中 (即为0 即软解析)
Optimizer mode: ALL_ROWS
Parsing user id: SYSTEM
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
107 107 107 TABLE ACCESS FULL EMPLOYEES (cr=12 pr=3 pw=0 time=961
us starts=1 cost=2 size=7383 card=107)




