ITPub博客

首页 > 数据库 > Oracle > fast parse,soft parse,hard parse的区别

fast parse,soft parse,hard parse的区别

原创 Oracle 作者:gangyaocn 时间:2010-11-04 17:00:46 0 删除 编辑

http://www.itpub.net/thread-877110-1-5.html

Subject: SQL Parsing Flow Diagram
Doc ID: Note:32895.1 Type: REFERENCE
Last Revision Date: 20-OCT-2005 Status: PUBLISHED


PURPOSE
~~~~~~~
The document gives a overview of Parsing.

SCOPE & APPLICATION
~~~~~~~~~~~~~~~~~~~
For users requiring a general overview of how parsing works.


Introduction
============

This article show the parsing mechanism as a flow diagram.
Its main purpose is to show the difference between a 'soft' and a
'hard' parse.

It is intended to give a feel of how parsing operates to make
explanation of parsing activity easier.


SQL Parsing Flow Diagram
========================

PHP code:



Statement


Submitted


|


Is it in an open cursor?--------------YES----V


| |


NO |


| |


Is SESSION_CACHED_CURSORS = Value |


and
cursor in --------------YES----V In these 3 cases we


Session Cursor cache
? | know that the cursor has


| | already been parsed, so


NO
| re-parsing is


| | unnecessary.


Is HOLD_CURSOR=Y |


and
cursor in --------------YES----V


Held cursor cache
? |


| |


NO |


| | ^


OPEN A CURSOR | CLIENT SIDE |


| | -------------|


Statement is Hashed and compared | SERVER SIDE |


with the Hashed value in the sql area | V


| V


Is it in sql area
? --YES-(Soft Parse)--> ---------


| | |


NO | EXECUTE |


| | |


PARSE STATEMENT ('Hard' Parse)---------> ---------

NOTES
=====

1. A cursor is an address on the client that points to the memory
location of a SQL statement on the server.
Multiple-client cursors may point at the same address on the server.

2. Remember that 'Client' and 'Server' sides may reside on the same
machine - in which case Client/Server is a logical distinction.

3. If a cursor is open, then the statement will be in the sql_area,
so no parsing is necessary.

This is why locks may remain when a client is terminated
abnormally (such as a PC Client being turned off without
closing open cursors).

4. SESSION_CACHED_CURSORS is the initialisation parameter that
specifies how many cursors to hold open for a particular session.

5. HOLD_CURSOR is an precompiler parameter that specifies that an
individual cursor should be held open.

See Page 11-3 of the Programmer's guide to the Oracle Precompilers.

6. Both the soft and hard parse register as a parse in tkprof. Hashing the
current statement updates the parse count.

7. Soft parse avoids many of the steps taken during the parse phase for a
particular statement. Initial syntactic and semantic checks are made and
then the statement is hashed and compared with hashed statements in
the SQL area. If a match is found, then existing information is used
and relatively expensive steps (such as query optimization etc.) are avoided.

8. The 10053 event is only invoked during a hard parse.


Additional Search Words
~~~~~~~~~~~~~~~~~~~~~~~
SQL语句的处理过程修正

对照metalink给出的这个示意图,我们可以对SQL的处理过程作如下的描述:
1、检查是否有打开的游标,如果有,则直接通过游标link到位于PGA的private SQL AREA( private SQL area),转步骤11。否则,执行步骤2。
2、检查初始化参数SESSION_CACHED_CURSORS是否被设置,如果被设置,则同样可以通过游标指向到位于PGA的私有SQL AREA,转步骤11。否则执行步骤3。
3、检查HOLD_CURSOR以及RELEASE_CURSOR的设置。如果RELEASE_CURSOR=no(默认 no),HOLD_CURSOR=yes(默认为no),当ORACLE执行完SQL语句,为private SQL AREA分配的内存空间被保留,cursor和private SQL AREA之间的link也被保留,预编译程序不再使用它,同样可以通过这个指针直接在private SQL AREA获得语句,转步骤11。
这上面的三种情况,实际上都没有作任何parse,都是直接从位于PGA中的private SQL AREA获得语句并直接执行。此为fast parse。
这三种情况都不存在的情况下,oracle转到步骤4执行。
4、创建一个游标。
5、语法检查Syntax Check:检查语法书写是否正确,是否符合SQL Reference Manual中给出的SQL语法。
6、语义分析Semantic Analysis:查找数据字典,检查表、列是否正确,在所要求的对象上获取语法分析锁,使得在语句的语法分析过程中不改变这些对象的定义, 验证为存取所涉及的模式对象所需的权限是否满足。
7、将语句转化成ASCII等效数字码,再通过散列算法得到散列值。
8、检查库缓存中是否存在同样hash值的语句。如果存在,转步骤11。否则,执行步骤9。 这就是soft parse。
9、选择执行计划。从可用的执行计划中选择一个最优的执行计划,其中包括存储大纲(srored outline)或物化视图(materialized view)相关的决定。
10、生成该语句的一个编译代码(p-code)。
11、执行语句。


cursor:from Oracle9i Database Concepts:A cursor is a handle or name for a private SQL area--an area in memory in which a parsed statement and other information for processing the statement are kept.

当某个session执行一条语句之后,该语句的parse结果会在library cache中保存,同时也会在PGA的private sql area有一个拷贝的副本。

cursor 总是通过一个link是直接链到 private sql area的。如果在private中没有找到这个副本,就需要对SQL进行parse,然后再在library cache中进行hash值的匹配。所以总的来说,使用cursor能不需要任何parse,就是因为直接从当前的private sql area中得到了语句相关信息,包括执行计划。而一旦需要到library cache中进行匹配,就必须需要parse。
soft parse不是不作parse,只是parse的量比较小,只需要作语法检查和语义分析,以及散列语句。


关于预编译的两个参数说明:
HOLD_CURSOR
HOLD_CURSOR默认值为no,当oracle执行完sql语句,close游标之后,预编译程序将游标和缓存SQL的cache链接标记为可重 用。并且释放已经分配给该语句的私有SQL AREA内存区域,解除parse locks。当有下一个语句需要使用时,这个链接立即被重用。
当HOLD_CURSOR=YES时,当oracle执行完sql语句,为private SQL AREA分配的内存空间被保留,cursor和private SQL AREA之间的link也被保留,预编译程序不再使用它。

RELEASE_CURSOR
RELEASE_CURSOR的优先级高于HOLD_CURSOR。RELEASE_CURSOR默认值为no。RELEASE_CURSOR=yes, 当oracle执行完sql语句,close游标之后,缓存被释放,锁被解除,链接被标识为可重用。RELEASE_CURSOR=no,则主要有 HOLD_CURSOR来决定了。
另外说明一点,这两个参数是在预编译的文件中定义的。
这部分内容详细见:
oracle documents -> Programmer's Guide to the Oracle Precompilers -> Performance Tuning
-> Optimizing SQL Statements -> Using the Cursor Management Options

----------------------

from Oracle doc(Oracle Database Programmer's Guide to the Oracle Precompilers
10gR2)
)

Eliminating Unnecessary Parsing

Eliminating unnecessary parsing requires correct handling of cursors and selective use of the following cursor management options:

  • MAXOPENCURSORS

  • HOLD_CURSOR

  • RELEASE_CURSOR

These options affect implicit and explicit cursors, the cursor cache, and private SQL areas.

You can use the ORACA to get cursor cache statistics. See "Using the Oracle Communications Area".

Handling Explicit Cursors

Recall that there are two types of cursors: implicit and explicit. Oracle implicitly declares a cursor for all data definition and data manipulation statements. However, for queries that return more than one row, you must explicitly declare a cursor (or use host arrays). You use the DECLARE CURSOR statement to declare an explicit cursor. How you handle the opening and closing of explicit cursors affects performance.

If you need to reevaluate the active set, simply reopen the cursor. The OPEN statement will use any new host-variable values. You can save processing time if you do not close the cursor first.

To make performance tuning easier, the precompiler lets you reopen an already open cursor. However, this is an Oracle extension to the ANSI/ISO embedded SQL standard. So, when MODE=ANSI, you must close a cursor before reopening it.

Only CLOSE a cursor when you want to free the resources (memory and locks) acquired by opening the cursor. For example, your program should close all cursors before exiting.

Cursor Control

In general, there are three ways to control an explicitly declared cursor:

  • Use the DECLARE, OPEN, and CLOSE statements

  • Use the PREPARE, DECLARE, OPEN, and CLOSE statements

  • COMMIT closes the cursor when MODE=ANSI

With the first way, beware of unnecessary parsing. The OPEN statement does the parsing, but only if the parsed statement is unavailable because the cursor was closed or never opened. Your program should DECLARE the cursor, reopen it every time the value of a host variable changes, and CLOSE it only when the SQL statement is no longer needed.

With the second way (dynamic SQL Methods 3 and 4), the PREPARE statement does the parsing, and the parsed statement is available until a CLOSE statement is executed. Your program should prepare the SQL statement and DECLARE the cursor, reopen the cursor every time the value of a host variable changes, rePREPARE the SQL statement and reopen the cursor if the SQL statement changes, and CLOSE the cursor only when the SQL statement is no longer needed.

When possible, avoid placing OPEN and CLOSE statements in a loop; this is a potential cause of unnecessary reparsing of the SQL statement. In the next example, both the OPEN and CLOSE statements are inside the outer while loop. When MODE=ANSI, the CLOSE statement must be positioned as shown, because ANSI requires a cursor to be closed before being reopened.

EXEC SQL DECLARE emp_cursor CURSOR FOR 
SELECT ename, sal from emp where sal > :salary and
sal <= :salary + 1000;
salary = 0;
while (salary < 5000)
{
EXEC SQL OPEN emp_cursor;
while (SQLCODE==0)
{
EXEC SQL FETCH emp_cursor INTO ....
...
}
salary += 1000;
EXEC SQL CLOSE emp_cursor;
}

With MODE=ORACLE, however, a CLOSE statement can execute without the cursor being opened. By placing the CLOSE statement outside the outer while loop, you can avoid possible reparsing at each iteration of the OPEN statement.

... 
while (salary < 5000)
{
EXEC SQL OPEN emp_cursor;
while (sqlca.sqlcode==0)
{
EXEC SQL FETCH emp_cursor INTO ....
...
}
salary += 1000;
}
EXEC SQL CLOSE emp_cursor;

Using the Cursor Management Options

A SQL statement need be parsed only once unless you change its makeup. For example, you change the makeup of a query by adding a column to its select list or WHERE clause. The HOLD_CURSOR, RELEASE_CURSOR, and MAXOPENCURSORS options give you some control over how Oracle manages the parsing and reparsing of SQL statements. Declaring an explicit cursor gives you maximum control over parsing.

Private SQL Areas and Cursor Cache

When a data manipulation statement is executed, its associated cursor is linked to an entry in the cursor cache. The cursor cache is a continuously updated area of memory used for cursor management. The cursor cache entry is in turn linked to a private SQL area.

The private SQL area, a work area created dynamically at run time by Oracle, contains the parsed SQL statement, the addresses of host variables, and other information needed to process the statement. An explicit cursor lets you name a SQL statement, access the information in its private SQL area, and, to some extent, control its processing.

represents the cursor cache after your program has done an insert and a delete.

Figure C-2 Cursors Linked through the Cursor Cache

Cursor linked through the cursor cache
Description of "Figure C-2 Cursors Linked through the Cursor Cache"

Resource Use

The maximum number of open cursors in each user session is set by the Oracle initialization parameter OPEN_CURSORS.

MAXOPENCURSORS specifies the initial size of the cursor cache. If a new cursor is needed and there are no free cache entries, Oracle tries to reuse an entry. Its success depends on the values of HOLD_CURSOR and RELEASE_CURSOR and, for explicit cursors, on the status of the cursor itself.

If the value of MAXOPENCURSORS is less than the number of cache entries actually needed, Oracle uses the first cache entry marked as reusable. For example, suppose the cache entry E(1) for an INSERT statement is marked as reusable, and the number of cache entries already equals MAXOPENCURSORS. If the program executes a new statement, cache entry E(1) and its private SQL area might be reassigned to the new statement. To reexecute the INSERT statement, Oracle would have to reparse it and reassign another cache entry.

Oracle allocates an additional cache entry if it cannot find one to reuse. For example, if MAXOPENCURSORS=8 and all eight entries are active, a ninth is created. If necessary, Oracle keeps allocating additional cache entries until it runs out of memory or reaches the limit set by OPEN_CURSORS. This dynamic allocation adds to processing overhead.

Thus, specifying a low value for MAXOPENCURSORS saves memory but causes potentially expensive dynamic allocations and deallocations of new cache entries. Specifying a high value for MAXOPENCURSORS assures speedy execution but uses more memory.

Infrequent Execution

Sometimes, the link between an infrequently executed SQL statement and its private SQL area should be temporary.

When HOLD_CURSOR=NO (the default), after Oracle executes the SQL statement and the cursor is closed, the precompiler marks the link between the cursor and cursor cache as reusable. The link is reused as soon as the cursor cache entry to which it points is needed for another SQL statement. This frees memory allocated to the private SQL area and releases parse locks. However, because a prepared cursor must remain active, its link is maintained even when HOLD_CURSOR=NO.

When RELEASE_CURSOR=YES, after Oracle executes the SQL statement and the cursor is closed, the private SQL area is automatically freed and the parsed statement lost. This might be necessary if, for example, MAXOPENCURSORS is set low at your site to conserve memory.

If a data manipulation statement precedes a data definition statement and they reference the same tables, specify RELEASE_CURSOR=YES for the data manipulation statement. This avoids a conflict between the parse lock obtained by the data manipulation statement and the exclusive lock required by the data definition statement.

When RELEASE_CURSOR=YES, the link between the private SQL area and the cache entry is immediately removed and the private SQL area freed. Even if you specify HOLD_CURSOR=YES, Oracle must still reallocate memory for a private SQL area and reparse the SQL statement before executing it because RELEASE_CURSOR=YES overrides HOLD_CURSOR=YES.

Nonetheless, when RELEASE_CURSOR=YES, the reparse might not require extra processing because Oracle caches the parsed representations of SQL statements and PL/SQL blocks in its Shared SQL Cache. Even if its cursor is closed, the parsed representation remains available until it is aged out of the cache.

Frequent Execution

The links between a frequently executed SQL statement and its private SQL area should be maintained, because the private SQL area contains all the information needed to execute the statement. Maintaining access to this information makes subsequent execution of the statement much faster.

When HOLD_CURSOR=YES, the link between the cursor and cursor cache is maintained after Oracle executes the SQL statement. Thus, the parsed statement and allocated memory remain available. This is useful for SQL statements that you want to keep active because it avoids unnecessary reparsing.

When HOLD_CURSOR=YES and RELEASE_CURSOR=NO (the default), the link between the cache entry and the private SQL area is maintained after Oracle executes the SQL statement and is not reused unless the number of open cursors exceeds the value of MAXOPENCURSORS. This is useful for SQL statements that are executed often because the parsed statement and allocated memory remain available.

Using the defaults, HOLD_CURSOR=YES and RELEASE_CURSOR=NO, after executing a SQL statement with an earlier Oracle version, its parsed representation remains available. With Oracle database version 7, under similar conditions, the parsed representation remains available only until it is aged out of the Shared SQL Cache. Normally, this is not a problem, but you might get unexpected results if the definition of a referenced object changes before the SQL statement is reparsed.

Parameter Interactions

shows how HOLD_CURSOR and RELEASE_CURSOR interact. Notice that HOLD_CURSOR=NO overrides RELEASE_CURSOR=NO and that RELEASE_CURSOR=YES overrides HOLD_CURSOR=YES.

Table C-1 HOLD_CURSOR and RELEASE_CURSOR

HOLD_CURSOR RELEASE_CURSOR Links are:

NO

NO

marked as reusable

YES

NO

maintained

NO

YES

removed immediately

YES

YES

removed immediately

[@more@]

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26651/viewspace-1040920/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-01-17

  • 博文量
    37
  • 访问量
    114401