Oracle一個SQL語句的處理過程(轉)

wangkxxe發表於2009-06-24

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 area        |              V
 |                                            V
 Is it in sql area? --YES-(Soft Parse)--&gt ---------
 |                                       |         |
 NO                                      | EXECUTE |
 |                                       |         |
 PARSE STATEMENT ('Hard' Parse)---------&gt ---------------------------------

對照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),當執行完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

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12801008/viewspace-607457/,如需轉載,請註明出處,否則將追究法律責任。

相關文章