一 , Library cache存放什么(存放的信息單元都叫做對象) ?  


Library存放的信息單元都叫做對象,這些對象可以分為兩類: 


1. 存儲對象
2. 過渡對象(游標Cursor,這里的游標指生成的可執行的對象, 運行相同SQL的多個進程可以共享該SQL產生的游標,節省內存。)


A. 用戶提交的SQL
B. SQL語句相關的解析樹
C. 執行計劃
D. 用戶提交的PL/SQL程序塊(包括匿名程序塊,procedure,packages,function等)
E. PL/SQL對象依賴的table,index,view等對象
F. 控制結構:lock,pin,dependency table 等


備注: LIBRARY CACHE的對象可以在V$DB_OBJECT_CACHE中找到,這個視圖基于X$KGLOB。

二, SQL的解析及游標


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



1.  將父游標保存到Library Cache中 (父游標的概念參考后面的說明,這一步其實不包含
    在解析過程中)


     先將SQL轉化為ASCII數值,然后對這些ASCII數值進行hash函數的運算生成hash value    (10g還有唯一的SQL_ID),運算后匹配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,也就是句柄,    如果匹配成功,那么去找子游標 (子游標的概念參考后面的說明,找到子游標那么直接執行,    如果子游標被交換出庫緩存, 那么通過父游標信息重新構造reload一個子游標) , 如果不成功,    即不存在共享的父游標,就會在庫緩存中分配一些內存(Chunk),并將新產生的父游標保存進    庫緩存,生成一個handle(對象句柄),掛載hash bucket上。接下來進行硬解析。


2 . 包含VPD(虛擬專用數據庫)的約束條件
      虛擬專用數據庫VPD詳細信息見后備注。比如對于HR工資的查詢,select salary from emp ;       如果設置VPD, 會隱含加入每個用戶各自的賬號,只能查看自己的,句子會變成類似:       select salary from emp where name=\\\’susan\\\’ ;  


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


4.  到數據字典校驗SQL涉及的對象和列是否存在,不存在就退出解析過程,這個過程會加載    Dictionary Cache .


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


6.  檢查發出SQL語句的用戶(一般指連接用戶)是否有訪問SQL中引用的對象的權限,若沒有則 退出解析。


7.  邏輯優化 — 用一定的轉換技巧(Transforming Queries,查詢轉換器),生成語法語義上等同    的新的SQL語句。查詢語句的形式會影響所產生的執行計劃,查詢轉換器的作用就是改變查詢語    句的形式以產生較好的執行計劃。四種常見轉換技術:視圖合并(View Merging)、謂詞推進   (Predicate Pushing)、非嵌套子查詢(Subquery Unnesting)和物化視圖的查詢重寫(Query
    Rewrite with Materialized Views)。 


  詳細可以參考以下文檔及后面備注 :  
  http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/optimops.htm#i37745


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


9.  將子游標load到庫緩存 — 首先分配內存(Chunk),然后將共享子游標存儲進去,最后將它與父游標    關聯,與子游標有關的關鍵內容是執行計劃和執行環境,一旦保存到庫緩存,父游標與子游標就可以 分別通過視圖v$sqlarea和v$sql被具體化。


v$sql中通過child_number,hash_value,address來確定一個子游標,而v$sqlarea通過address和hash_value可以確定一個父游標; 而從10g過后,通過sql_id就能確定一個游標; 查找是否有共享的父游標
和硬解析是兩個不同的過程,父游標共享與否和硬解析沒有直接關系,子游標的共享狀態決定軟硬解析 。

備注: 
———————————————————————————- 


Namespace:
使用hash算法對SQL語句對應的ASCII進行運算時,傳入函數的參數有SQL語句名稱及namespace(可通過v$librarycache查詢到各種不同的namespace,對于SQL而言值為SQL AREA) .


VPD虛擬專用數據庫的詳細信息:
http://www.oracle.com/technology/global/cn/pub/articles/10gdba/week14_10gdba.html


SQL Parsing Flow Diagram [ID 32895.1] 
https://support.oracle.com/CSP/main/article?cmd=show&type=NOT&id=32895.1



解析過程中的邏輯優化部分的查詢轉換器 — 


從Oracle 8i開始就有四種轉換技術:視圖合并(View Merging)、謂詞推進(Predicate Pushing)、非嵌套子查詢(Subquery Unnesting)和物化視圖的查詢重寫(Query Rewrite with Materialized Views)。
 
視圖合并:如果SQL語句中含有視圖,經分析后會把視圖放在獨立的“視圖查詢塊”中,每個視圖會產生一個視圖子計劃,當為整個語句產生執行計劃時,視圖子計劃會被直接拿來使用而不會照顧到語句的整體性,這樣就很容易導致不良執行計劃的生成。視圖合并就是為了去掉“視圖查詢塊”,將視圖合并到一個整體的查詢塊中,這樣就不會有視圖子計劃產生,執行計劃的優良性得到提升。


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


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


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


———————————————————————————- 


三, 父游標與子游標 



部分內容參考: 
http://www.oraclefans.cn/forum/showblog.jsp?rootid=5553 
http://www.itpub.net/thread-1362874-1-1.html  (問題)    


在硬解析的過程中,進程會一直持有library cache latch,直到硬解析結束。硬解析過程會為該SQL產生兩個游標,一個是父游標,另一個是子游標。

父游標和子游標相關問題的討論:
http://www.itpub.net/thread-1362874-1-1.html 



父游標(parent cursor) —


當用戶A發出一條SQL后,Oracle會根據SQL文本內容生成hash value(10g還有唯一的SQL_ID),對比庫緩存中的hash value, 以便能夠快速找到Shared pool中已經存在的相同SQL。如果找不到,則Oracle會為這個SQL創建一個parent cursor和一個child cursor。


父游標里主要包含兩種信息:SQL文本以及優化目標(optimizer goal)。從v$sqlarea視圖中看到的都是有關父游標的信息,v$sqlarea中的每一行代表了一個parent cursor,  比如SQL文本對應字段SQL_TEXT, 優化目標(optimizer goal)對應后面的RUNTIME_MEM,EXECUTIONS,CPU_TIME, DISK_READS, BUFFER_GETS 等等 。


父游標在第一次打開時被鎖定,直到其他所有的session都關閉游標后才被解鎖。當父游標被鎖定的時候它是不能被交換出library cache的,只有在解鎖以后才能被交換出library cache,這時該父游標對應的所有子游標也被交換出library cache。


一個CURSOR的結構包括PARENT CURSOR和CHILD CURSOR,每個CURSOR至少包含一個CHILD CURSOR。這個CURSOR通過HASHVALUE來區別,每個PARENT CURSOR至少包含一個HEAP0,里面存放環境、狀態和綁定變量的信息。每個PARENT CURSOR至少有一個CHILD CURSOR 。handle其實就是存放的父游標,真正的執行計劃是存放在子游標上的,也就是heap6上。


PARENT CURSOR是由一個handle和一個object組成,可以通過在庫緩存hash table中的hash value查找到handle, 而object 包含了指向它的每個 child cursor的指針 。


V$SQLAREA中version_count看到一個父游標對應多少個子游標,對應關系是靠hash_value及adress(SQL文本的地址)聯系的,V$SQL中相同SQL文本的不同子游標,hash_value及adress是相同的,但是子地址child_address卻不一樣,這里的子地址實際就是子游標所對應的Heap0的句柄(handel)。 V$SQL中的hild_number編號從0開始,同樣SQL文本(父游標共享)不同的child_number對應不同的child_address 。Oracle10g版本下V$SQL中有有3個字段bind_data,
optimizer_env , optimizer_env_hash_value 應該是用于決定取哪個子游標的字段。不過9i 中v$sql中沒有這些字段,具體如何查找到子游標的參考討論 :
http://www.itpub.net/thread-1362874-1-1.html  



子游標 (Child Cursors) —


子游標包括游標所有的信息,比如具體的執行計劃、綁定變量等。子游標隨時可以被交換出library cache,當子游標被交換出library cache時,oracle可以利用父游標的信息重新構建出一個子游標來,這個過程叫reload。 子游標具體的個數可以從v$sqlarea的version_count字段體現出來。而每個具體的子游標則全都在v$sql里體現。可以使用下面的方式來確定reload的比率:
SELECT 100*sum(reloads)/sum(pins) Reload_Ratio FROM v$librarycache;


一個父游標可以對應多個子游標。當具體的綁定變量的值與上次的綁定變量的值有較大差異(比如上次執行的綁定變量的值的長度是6位,而這次執行的綁定變量的值的長度是200 位)時或者當SQL語句完全相同,但是所引用的對象屬于不同的schema時,或執行SQL的環境不同(優化器模式不一樣), 都會創建一個新的子游標。



關于子游標新建和reload 的區別,如果所有版本的子游標都不能被共享,那么會創建一個新的子游標 (new create) ,這種情況指的就是 environment 或bind var 長度不一樣等 導致的情況 ;而reload 指的是父游標可以共享, 同樣的子游標 (environment 或bind var 等都一樣)原來已經存在于library cache, 因為某種原因被aged out出去,而現在需要它了,要重新裝載回來。



每個child cursor也是由一個handle和一個object構成. child object 又是由兩個heap即heap0及heap6 組成,其中Heap0包含所有的針對SQL語句每個版本的標示信息(比如Environment, Statistics, Bind Variables等,比如綁定變量值不同的長度可能導致sql解析版本的不同; Child cursors are also called versions. ),Heap6包含執行計劃 。


Child cursor包含了SQL的metadata,也就是使這個SQL可以執行的所有相關信息,如OBJECT和權限,優化器設置,執行計劃等。v$sql中的每一行表示了一個child cursor,根據hash value和address與parent cursor 關聯。child cursor有自己的address,即V$SQL.CHILD_ADDRESS。如果有多個child cursor,則表示parent cursor有多個版本,v$sqlarea中的version_count字段就會紀錄下來。

每種類型的dml語句都需要如下階段:


Create a Cursor         創建游標
Parse the Statement     解析語句
Bind Any Variables      綁定變量
Run the Statement       運行語句
Close the Cursor        關閉游標


四,  硬解析與軟解析,軟軟解析,RELOAD



硬解析 — 
首先了解父游標共享的條件 :


1. 字符級的比較, 要求文本完全一致
   SQL語句必須完全相同,select * from emp; 和select     *  from emp; 是不一樣的。不能共享。


2. 必須使用相同名稱的綁定變量(其實就是文本字符不一致),比如
   select age from pepoo where name=:var_p
   select age from pepoo where name=:var_f
   (即使在運行的時候賦予這兩個不同名稱的綁定變量一樣的值,也不能通向父游標)


從SQL解析過程可以看出,父游標是否共享是發生在硬解析之前,所以父游標是否能共享和硬解析沒有關系,不過父游標不能共享則一定是硬解析,硬解析的整個過程見上面的第二節 。但是父游標共享了不一定就是軟解析。能否避免硬解析,還要看子游標 。

——————————————————— 
父游標共享已經討論過,這里討論子游標共享的幾種情況 (假設CURSOR_SHARING=EXACT ):   


第一種是A發出的原始SQL語句和其他用戶B之前發出的SQL文本一模一樣,父親游標可以共享,但是因為優化器環境設置不同( OPTIMIZER_MISMATCH),  綁定變量的值的長度在第二次執行的時候發生顯著的變化(BIND_MISMATCH) , 授權關系不匹配(AUTH_CHECK_MISMATCH ) 或者 基礎物件轉換不匹配(TRANSLATION_MISMATCH) 等導致子游標不能共享,需要新生成一個子游標 。 這與SQL共享(即游標共享)是有關系的 。 這種情況下的執行計劃可能不同,也可能相同(我們可以通過plan_hash_value看出);  
這里因為除SQL TEXT之外的其他條件不符合,所以reload 也不會發生 。子游標就是new create and load,應該是硬解析 。具體的mismatch可以查詢 V$SQL_SHARED_CURSOR .   ;


例如:


–窗口1執行


sys/SYS>alter session set optimizer_mode=all_rows;
Session altered.


sys/SYS>select * from tt;
no rows selected


sys/SYS>alter session set optimizer_mode=first_rows_10;
Session altered.


sys/SYS>select * from tt;
no rows selected



–窗口2執行


sys/SYS>select hash_value,sql_text,executions,VERSION_COUNT from
        v$sqlarea where sql_text like \\\’%from tt\\\’;


HASH_VALUE SQL_TEXT                                 EXECUTIONS VERSION_COUNT
———- —————————————- ———- ————-
3762890390 select * from tt                                  2             2


sys/SYS>select HASH_VALUE,child_number,sql_text from v$sql where sql_text like \\\’%from tt\\\’;


HASH_VALUE CHILD_NUMBER SQL_TEXT
———- ———— —————————————-
3762890390            0 select * from tt
3762890390            1 select * from tt


可以看到,SQL文本是完全相同的,所以兩個子游標共享了一個父游標。但是由于optimizer_mode的不同,所以生成了2個子游標。如果產生了子游標,那么說明肯定產生了某種mismatch,如何來查看是何種原因產生了mismatch,要通過v$sql_shared_cursor。


sys/SYS>select kglhdpar, address,auth_check_mismatch, translation_mismatch,OPTIMIZER_MISMATCH
  2  from v$sql_shared_cursor
  3  where kglhdpar in
  4  ( select address
  5    from v$sql
  6    where sql_text like \\\’%from tt\\\’);


KGLHDPAR ADDRESS  A T O
——– ——– – – –
89BB8948 89BB83CC N N N
89BB8948 89BB5E78 N N Y   


可以看到OPTIMIZER_MISMATCH列第二行的值為Y,這說明了正是由于optimizer_mode的不同而產生了子游標。最后,父游標和子游標的意義何在?其實一切都是為了共享。以減少再次解析的資源浪費。



第二種是A發出的原始SQL語句和與在shared pool 中的SQL文本一模一樣,父游標可以共享,子游標不存在所謂的mismatch ,  目前也存在于庫緩存中,可以共享子游標,那么應該是軟解析 。


第三種,父游標可以共享, 不同的是,子游標本來是可以共享的,但是目前被交換出(aged out)庫緩存,這時會reload 子游標,也就是利用父游標的信息重新構造出一個子游標 ,Oracle已經知道應該共享哪個子游標,只是它暫時被交換出庫緩存, reload應該不屬于硬解析,是否屬于軟解析呢 ?雖然被aged out 出庫緩存,但是可能某個地方會記錄這個子游標的一些信息,而不需要重新生成子游標的相關信息(比如執行計劃等),  而只需要reload  (reload的具體過程是什么還需要研究)  。


查找是否有共享的父游標和硬解析是兩個不同的過程,父游標共享與否和硬解析沒有直接關系, 子游標的共享狀態決定軟硬解析 。


——————————————————— 



從性能的角度來看,盡量避免硬解析,為什么?
第一: 因為邏輯優化(Transforming Queries)和物理優化(選擇最優執行計劃)都非常依賴CPU的操作。
第二: 需要分配內存來將父游標與子游標保存到庫緩存中。由于庫緩存是在所有的會話之間共享,
庫緩存中的內存分配必須是串行執行。


軟解析,軟軟解析 — 


軟解析是相對于硬解析而言的,其實只要在hash bucket里可以匹配對應的SQL文本(算一次get),那么就是軟解析,說明之前運行過該sql,其實sql執行期間只要一個或多個步驟可以跳過,那么我們就可以定位為軟解析。如果這個SQ語句沒有被找到,就進行硬解析。軟解析有三種類型:


A.  第一種是某session發出的SQL語句與在library cache里其他session發出的SQL一致,父游標和子游標都可以共享,邏輯優化(Transforming Queries),和物理優化(選擇最優執行計劃)及將這些信息裝載到庫緩存的heap中 這幾個步驟可以省略,表名,列名,名稱轉化及權限檢查還是需要的。


B.  第二種是某session發出的SQL是該session之前發出的曾經執行過的SQL。這時,解析過程只需要進行文法檢查及權限檢查。


C.  第三種是當設置了session_cached_cursors時,當某個session第三次執行相同的SQL時,則會把該SQL的游標信息轉移到該session的PGA中。這樣,該session以后再執行相同的SQL語句時,會直接從PGA里取出執行計劃,跳過硬解析的所有步驟,這是最高效的解析方式,但是會消耗很大的內存。俗稱為軟軟解析 。

Reload — 


關于子游標新建和reload 的區別,如果各版本的子游標都不能被共享,那么會創建一個新的子游標 (new create) ,這種情況指的就是 environment 或綁定變量長度不一樣等 導致的情況。 而reload 指的是父游標可以共享,同樣的子游標 (執行計劃,environment 或bind var 等都一樣)原來已經存在于library cache, 因為某種原因被aged out出去,而現在需要它了,要重新裝載回來 (Oracle數據庫可能在某個地方保存了原來相同的子游標信息)。


在Hash bucket中查找SQL,如果有的話就算作是一次get,并查找這個SQL語句的執行計劃,如果執行計劃已經不存在了(age out)或者是存在但不可用(Invalidation),那么就必須對這條sql語句重新裝載,這就叫reload,如果執行計劃存在并且可用的話,oracle就執行這句話,這就叫做execution

五, 綁定變量(Bind Variables)



優點: 共享游標,減少硬解析


綁定變量分級 —


前面說到執行環境的變化比如綁定變量定義的類型大小不同會導致生成不同的游標,為了使游標的數量不至于太多,產生了這個功能。此功能將變量的長度分為4個級別,0-32字節,33-128字節,129-2000字節,>2000字節 這四個等級。不用說,同一個綁定變量(長度)的變化,最多能生成4個游標。


缺點:  綁定變量也有缺點。缺點就是,相對于字面量而言,會減弱查詢優化器的功能。


比如:
select count(*) from t where id > 10;
select count(*) from t where id > 99999;
根據id值10,99999和表的統計信息,查詢優化器可能會選擇全表掃描或者索引掃描,是合理的。


使用了綁定變量,優化器會忽略他們的具體值,從而生成相同的執行計劃。為了解決這個問題,
oracle9i引入了綁定變量窺測(bind variable peeking)的功能。


綁定變量窺測的優點,就是窺測綁定變量的值,把它們當做字面量來使用。這樣的好處,就是能獲得最優查詢路徑,比如是選擇全表掃描還是索引掃描。


綁定變量窺測也有缺點,即生成的執行計劃依賴第一次生成執行計劃時所提供的值。舉例來說,就是如果第一次是全掃描,以后永遠都是全表掃描了。這個方法對于非OLTP系統的缺點非常明顯,因為一個綁定變量集可能返回的結果集只包含幾百行的數據,而另一套綁定變量可能返回幾百萬行數據,因此,Oracle建議保留CURSOR_SHARING作為該初始化參數的默認值,以強制產生一個新的更有效的執行計劃 (cursor_sharing的詳細解釋見后面)。


那么如何避免這個缺點呢?只有升級到oracle11g了。
oracle11g引用一個新功能,自適應游標共享(ACS)。這個功能就是根據綁定變量的值,可以為相同的sql語句,生成不同子游標,及不同的執行計劃。ACS使用了兩個新的度量機制:綁定敏感度和綁定感知。具體可以參考Oracle11g文檔。



什么時候不使用綁定變量?
批量任務處理,報表生成,運用OLAP的數據倉庫,因為這種大型的查詢時間較長,一次新的硬解析相對于這個查詢時間不算什么, 所以不用綁定變量沒有什么影響 。如果使用綁定變量,10g或以前的版本,一旦第一次執行時綁定變量第一次提供的值如果是小范圍的,那么可能是索引掃描,但是第二次可能是數據倉庫典型的大時間范圍的查詢,需要全表掃描,但是還是沿用了前面的索引掃描,這樣導致性能下降。OLTP類型大多數是小量密集的操作,所以使用綁定變量時相對最優的執行計劃比較穩定 。 
 
在我們不使用where等條件判斷時我們就要盡量使用綁定變量(比如普通insert操作),沒理由不使用綁定變量;   而涉及到基數選擇性判斷時我們應該盡量避免使用綁定變量,因為在物理優化階段的綁定變量窺測遇到較大負面風險。


也可以參考下面的兩種建議:


如果sql處理的數據較少, 解析時間顯然比執行時間多很多了,那么我們應該盡量使用綁定變量,這種適用于 OLTP(聯機事務處理系統);
而如果是數據倉庫類型的數據庫,我們對綁定變量的使用就應該慎重了,因為這時的執行時間有可能遠遠大于解析時間,解析時間相對于執行時間近乎可以忽略,所以這時應該盡量不使用綁定變量。


參數CURSOR_SHARING —


oracle是為了滿足一些以前開發的程序,里面有大量的相似的statement,沒有很好的使用綁定變量,但是重寫有不現實的情況下使用的一個參數。并且oracle也不建議修改這個參數。保持默認即可。


語法 CURSOR_SHARING = { SIMILAR | EXACT | FORCE } ,默認值為 EXACT



EXACT —
僅僅允許絕對一樣的SQL語句共享同樣的游標。當一個SQL語句解析的時候,首先到shared pool區查看是否有完全一樣的語句存在,如果不存在(其實此時是找不到共享的父游標),就執行hard parse .


SIMILAR —
如果在shared pool中無法找到完全一樣的語句的時候,就會在shared pool進行一次新的查找,就是查找和當前要解析的語句相似的SQL語句。 similar語句就是除了value of some literal不同,別的地方都相同的語句。比如下面:
select * from a where age=2;
select * from a where age=5;
如果在shared pool中查找到這樣的語句,就會做下一步的檢查,看shared pool中緩存的這個語句的execution plan是否適合當前解析的語句,如果適合,就會使用shared pool的語句,而不去做hard parse。


FORCE —
強制將字面值不一樣的但是其他方面是一樣的SQL語句共享游標。如果cursor_sharing設置為force的時候,當在shared pool中發現了similar statement之后,就不會再去檢查執行計劃了,而直接使用在shared pool中的這個語句了。


將cursor_sharing設置為force實際上是危險的。這會可能形成suboptimal的執行計劃。比如對于一個范圍查找的語句,比如select * from a where a>10 and a<20這樣類型的語句,緩存中的語句的執行計劃可能對于正在解析的語句就是不適合的,不是最優的執行計劃。這樣看起來是減少了解析的時間,但是大大增大了execution的時間。


什么時候需要修改這個參數呢?需要滿足以下的條件:
一個是由于大量的shared pool hitmis影響了用戶的響應時間(就是當前的shared pool無法滿足共享sql語句存儲的需要),如果沒有這個問題,那么設置這個參數,可能會造成更糟糕的性能。這個參數僅僅只是減少parse的時間。另外一個就是在現有程序中有大量的similar statement,可通過設置這個參數來獲得相對比較好的性能。

—————————————————————
關于cursor_sharing = similar的測試 :
http://www.wangchao.net.cn/bbsdetail_60551.html


若存在object_id的 histograms ,則每次是不同的 值 的時候都產生硬解析 ,若不存在 histograms ,則不產生硬解析 。換句話說,當表的字段被分析過存在histograms的時候,similar 的表現和exact一樣,當表的字段沒被分析不存在histograms的時候,similar的表現和force一樣。這樣避免了一味地如force一樣轉換成變量形式,因為有hostograms的情況下轉換成變量之后就容易產生錯誤的執行計劃,沒有利用上統計信息。而exact呢,在沒有histograms的情況下也要分別產生硬解析,這樣的話,由于執行計劃不會受到數據分布的影響(因為沒有統計信息)重新解析是沒有實質意義的。而similar則綜合了兩者的優點。


備注: cursor_sharing=force  or similar時,在9205以下的版本BUG不少 。 
—————————————————————

Library cache內部機制詳解    參考:


http://www.hellodba.net/2010/07/oracle-library-cache.html 

更多關于云服務器域名注冊,虛擬主機的問題,請訪問三五互聯官網:m.shinetop.cn

贊(0)
聲明:本網站發布的內容(圖片、視頻和文字)以原創、轉載和分享網絡內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。郵箱:3140448839@qq.com。本站原創內容未經允許不得轉載,或轉載時需注明出處:三五互聯知識庫 » Library Cache 結構及內存管理 [final]

登錄

找回密碼

注冊