SQL解析過程中的查詢轉換 - Transforming Queries

tolywang發表於2010-10-28


SQL在解析階段主要完成以下步驟 :

1 . 包含VPD(虛擬專用資料庫)的約束條件
      虛擬專用資料庫VPD詳細資訊見後備注。比如對於HR工資的查詢,select salary from emp ;
      如果設定VPD, 會隱含加入每個使用者各自的賬號,只能檢視自己的,句子會變成類似:
      select salary from emp where name='susan' ;  

2.  對SQL語句進行文法檢查,如果存在文法錯誤,則退出解析過程  
      確認sql語句是否正確書寫(比如沒有寫from,select拼寫錯誤等),

3.  到資料字典校驗SQL涉及的物件和列是否存在,不存在就退出解析過程,這個過程會載入
    Dictionary Cache .

4.  將物件進行名稱轉換,比如將synonym 轉換為實際的物件等。若轉換失敗則退出解析。

5.  檢查發出SQL語句的使用者(一般指連線使用者)是否有訪問SQL中引用的物件的許可權,若沒有則
    退出解析。

6.  將父遊標儲存到Library Cache中 (父遊標的概念參考後面的說明)

     先將SQL轉化為ASCII數值,然後對這些ASCII數值進行hash函式的運算,運算後匹配
    library cache裡的hash bucket (hash bucket簡單來講是使用hash演算法將進入library
    cache中的SQL 透過一個類似二維陣列來表示,比如t[3][6], 每次查詢時透過hash演算法算出
    負荷的bucket號,找到對應bucket,比如前面t[3][6]中的3號,每個bucket後面會掛載所有
    滿足hash演算法的object handle, object handle會儲存SQL名稱[對於SQL而言就是SQL文字],
    namespace等) ,再匹配hash bucket上面的handle,也就是控制程式碼,如果匹配成功,那麼去找
    子游標 (子游標的概念參考後面的說明),如果不成功(即不存在共享的父遊標),就會在庫緩
    存中分配一些記憶體(Chunk),並將新產生的父遊標儲存進去,生成一個handle,這裡也就是硬解
    析,掛載hash bucket上。

7.  邏輯最佳化 -- 用一定的轉換技巧(Transforming Queries,查詢轉換器),生成語法語義上等同
    的新的SQL語句。查詢語句的形式會影響所產生的執行計劃,查詢轉換器的作用就是改變查詢語
    句的形式以產生較好的執行計劃。

  詳細可以參考:   
  


View Merging

Predicate Pushing

Subquery Unnesting

Query Rewrite with Materialized Views

OR-expansion 

 

     從Oracle 8i開始就有四種轉換技術:檢視合併(View Merging)、謂詞推進(Predicate Pushing)、非巢狀子查詢(Subquery Unnesting)和物化檢視的查詢重寫(Query Rewrite with Materialized Views)。
     

檢視合併:   如果SQL語句中含有檢視,經分析後會把檢視放在獨立的“檢視查詢塊”中,每個檢視會產生一個檢視子計劃,當為整個語句產生執行計劃時,檢視子計劃會被直接拿來使用而不會照顧到語句的整體性,這樣就很容易導致不良執行計劃的生成。檢視合併就是為了去掉“檢視查詢塊”,將檢視合併到一個整體的查詢塊中,這樣就不會有檢視子計劃產生,執行計劃的優良性得到提升。

謂詞推進:不是所有的檢視都能夠被合併,對於那些不能被合併的檢視Oracle會將相應的謂詞推進到檢視查詢塊中,這些謂詞通常是可索引的或者是過濾性較強的。

非巢狀子查詢:子查詢和檢視一樣也是被放於獨立查詢塊中的,查詢轉換器會將絕大多數子查詢轉換為連線從而合併為同一查詢塊,少量不能被轉換為連線的子查詢,會將它們的子計劃安照一個高效的方式排列。

物化檢視的查詢重寫:當query_rewrite_enabled=true時,查詢轉換器尋找與該查詢語句相關聯的物化檢視,並用物化檢視改寫該查詢語句。

 


8.  物理最佳化 -- 首先,生成與每個邏輯最佳化產生的sql語句有關的執行計劃, 接著, 根據
    資料字典找到相關的統計資訊或者動態收集的統計資訊,計算出與執行計劃相關的開銷。最後,
    選中最低開銷的執行計劃。涉及大量數學運算,所以這一步最消耗CPU資源。 子游標會在這一步生成 ,執行計劃及繫結變數是子游標中的主要內容。 

 

9.  將子游標儲存到庫快取  -- 首先分配記憶體,然後將共享子游標儲存進去,最後
將它與父遊標關聯,與子游標有關的關鍵內容是執行計劃和執行環境,一旦儲存到庫快取,父遊標
與子游標就可以分別透過檢視v$sqlarea和v$sql被具體化。

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

相關文章