SQL語句的解析過程 遊標週期

wangxiangtao發表於2011-08-30

遊標生命週期中的步驟:

(1)     開啟遊標: 在伺服器私有記憶體(使用者全域性區 User Global Area  UGA) 為這個遊標分配一個記憶體結構, 但是SQL語句與遊標還沒有關聯

(2)     解析遊標:當SQL語句與遊標關聯, 解析後的內容(執行計劃)載入到共享池(library cache) UGA中的結構被更新,儲存指向這個共享遊標在庫快取中的位置。

(3)     定義輸出變數:如果SQL語句有返回資料,須先定義接收資料的變數,eg select ,  使用returning 字句的 delete  insert   update

(4)     繫結輸入變數:  如果SQL語句使用了繫結變數, 此繫結不做任何檢查

(5)     執行遊標:  執行與遊標關聯的SQL 語句, 對於大多數型別的查詢,真正的處理過程是在(6) 步中的 獲取資料階段

(6)     獲取遊標: 如果SQL語句返回資料, 此步接收資料。對於查詢語句,完成大處理工作,遊標可能只讀取部分記錄, 不會迴圈到所有記錄的末端

(7)     釋放UGA中與遊標的相關資源  使資源能被其他遊標使用,但是library cache中的共享遊標不會被清除,使其得到重用。

 

使用dbms_sql包演示 遊標的整個過程:

 

declare

l_ename emp.ename%type :='SCOTT';

l_empno emp.empno%type;

l_cursor  integer;

l_retval integer;

begin

  l_cursor :=dbms_sql.open_cursor;

  dbms_output.put_line(l_cursor);

  dbms_sql.parse(l_cursor,'select empno from emp where ename=:ename',1);

  dbms_sql.define_column(l_cursor,1,l_empno);

  dbms_output.put_line(l_cursor);

  dbms_sql.bind_variable(l_cursor,':ename',l_ename);

  l_retval:=dbms_sql.execute(l_cursor);

  if dbms_sql.fetch_rows(l_cursor) > 0   then

    dbms_sql.column_value(l_cursor,1,l_empno);

    end if;

    dbms_sql.close_cursor(l_cursor);

 end;

 

 

解析過程:

(1)     包含vpd 的約束條件: SQL語句如果使用的表使用了行級安全控制,安全策略生成的約束條件新增到where

(2)     語法、語義、訪問許可權檢查: 檢查SQL語句書寫,物件是否存在, 該使用者是否有必要的許可權

(3)     父遊標快取:  library cache 中如果不存在共享的父遊標,將SQL語句的文字生存父遊標儲存在library cache

(4)     邏輯最佳化:使用不同的轉換技巧,生成語義上等同的新的SQL語句(SQL語句的改寫),此時增加執行計劃數量 和分配搜尋空間,為邏輯最佳化做準備。

(5)     物理最佳化:為邏輯最佳化階段的SQL語句產生執行計劃,讀取資料字典中的統計資訊以及動態取樣的統計資訊,計算開銷,選中低開銷的執行計劃。

(6)     儲存子游標:分配記憶體,儲存共享子游標, 與父遊標關聯。可以在v$sqlarea, v$sql 得到具體遊標資訊,父子游標 透過 sql_id 關聯。

 

因此 只完成(1) (2)兩步   相應的解析稱為軟解析; 當以上步驟全部執行時,相應的解析稱為硬解析

在整個解析過程中, 準確點講(1)(2) 是在UGA中進行,因為遊標是分為 session cursorshared  cursor 的, 我們平時說的parent cursor, child cursor 均屬於 shared cursor,其是快取在 library cache 的物件之一.

Session cursor其實就是 session 想對應的 server process UGA 的一塊記憶體區域。一個session cursor只能對應一個shared cursor,而一個shared cursor卻可能同時對應多個session cursor Session cursor 受以下三個引數的控制

open_cursors(session開啟session cursor的最大數量);

session_cached_cursors(session cache住遊標的數量);

cursor_space_for_time(當設定為ture後,library cache pin 會一直持有 直到parent cursor關閉,10.2.0.5 以上已經失效了此引數) 如下:

Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bit Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options

 

SQL> show parameter  cursor

 

NAME                                 TYPE        VALUE

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

cursor_sharing                       string      EXACT

cursor_space_for_time                boolean     FALSE

open_cursors                         integer     300

session_cached_cursors               integer     20

   因此 如果在同一個session 中,如果soft closed掉的session cursor已經和包含其執行計劃和parse treeshared cursor建立了聯絡, session執行同樣的SQL時, oracle 就不會再重複掃描 library cache(前提條件是沒有超出以上三個引數的閥值) 此過程稱為: 軟軟解析

 

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

相關文章