Oracle共享游標(biāo)有哪些

本篇內(nèi)容介紹了“Oracle共享游標(biāo)有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

創(chuàng)新互聯(lián)是一家專注于網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)與策劃設(shè)計(jì),佳木斯網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:佳木斯等地區(qū)。佳木斯做網(wǎng)站價(jià)格咨詢:18980820575

首先,明確一個(gè)概念,這里討論的游標(biāo)主要是共享游標(biāo)(shared cursor),跟SQL語句中定義的游標(biāo)(session cursor)不是一個(gè)概念。

共享游標(biāo)是用戶提交SQL或PL/SQL程序塊到Oracle的share pool之后,在library cache中生成的一個(gè)可執(zhí)行對(duì)象,這個(gè)對(duì)象我們稱之為游標(biāo)(cursor)。而SQL定義游標(biāo)則是SELECT語句產(chǎn)生的多行結(jié)果集,需要聲明、打開、提取、關(guān)閉。
游標(biāo)定義與分類

游標(biāo)包括shared cursor和session cursor:
shared cursor即是共享游標(biāo),是SQL語句在游標(biāo)解析階段生成獲得的,是位于library cache中的sql或匿名的pl/sql等。其元數(shù)據(jù)被在視圖V$sqlarea與v$sql中具體化。如果library cache中的父游標(biāo)與子游標(biāo)能夠被共享,此時(shí)則為共享游標(biāo)。父游標(biāo)能夠共享即為共享的父游標(biāo),子游標(biāo)能夠共享即為共享的子游標(biāo)。

session cursor即系統(tǒng)為用戶分配緩存區(qū),用于存放SQL語句的執(zhí)行結(jié)果。用戶可以通過這個(gè)中間緩沖區(qū)逐條取出游標(biāo)中的記錄并對(duì)其處理,直到所有的游標(biāo)記錄被逐一處理完畢。session cursor指的跟這個(gè)session相對(duì)應(yīng)的server process的PGA里(準(zhǔn)確的說是UGA)的一塊內(nèi)存區(qū)域(或者說內(nèi)存結(jié)構(gòu))即其主要特性表現(xiàn)在記錄的逐條定位,逐條處理。session cursor的元數(shù)據(jù)通過v$open_cursor視圖來具體化,每一個(gè)打開或解析的SQL都將位于該視圖。

游標(biāo)的生命周期


shared cursor生命周期

1)包含vpd的約束條件:SQL語句如果使用的表使用了行級(jí)安全控制,安全策略生成的約束條件添加到where子句中。
2)語法、語義、訪問權(quán)限檢查:檢查SQL語句書寫的正確性,對(duì)象存在性,用戶的訪問權(quán)限。
3)父游標(biāo)緩存:將該游標(biāo)(SQL語句)的文本進(jìn)行哈希得到哈希值并在library cache尋找相同的哈希值,如不存在則生存父游標(biāo)且保存在library cache中,按順序完成后續(xù)步驟。如果此時(shí)存在父游標(biāo),則進(jìn)一步判斷是否存在子游標(biāo)。若存在相同的子游標(biāo),則直接調(diào)用其子游標(biāo)的執(zhí)行計(jì)劃執(zhí)行該SQL語句,否則轉(zhuǎn)到下一步進(jìn)行邏輯優(yōu)化。
4)邏輯優(yōu)化:使用不同的轉(zhuǎn)換技巧,生成語義上等同的新的SQL語句(SQL語句的改寫),一旦該操作完成,則執(zhí)行計(jì)劃數(shù)量、搜索空間將會(huì)相應(yīng)增長(zhǎng)。其主要目的未進(jìn)行轉(zhuǎn)換的情況下是尋找無法被考慮到的執(zhí)行計(jì)劃。
5)物理優(yōu)化:為邏輯優(yōu)化階段的SQL語句產(chǎn)生執(zhí)行計(jì)劃,讀取數(shù)據(jù)字典中的統(tǒng)計(jì)信息以及動(dòng)態(tài)采樣的統(tǒng)計(jì)信息,計(jì)算開銷,開銷最低的執(zhí)行計(jì)劃將被選中。
6)子游標(biāo)緩存:分配內(nèi)存,生成子游標(biāo)(即最佳執(zhí)行計(jì)劃),與父游標(biāo)關(guān)聯(lián)??梢栽趘$sqlarea, v$sql得到具體游標(biāo)信息,父子游標(biāo)通過sql_id關(guān)聯(lián)。

對(duì)于僅僅完成步驟1與2的SQL語句即為軟解析,否則即為硬解析。SQL語句在Oracle中的執(zhí)行機(jī)理大概也類似這個(gè),具體可見“Oracle SQL語句執(zhí)行流程與順序原理解析”。

共享游標(biāo)包括父游標(biāo)和子游標(biāo)。

父游標(biāo)是在進(jìn)行硬解析時(shí)產(chǎn)生的,父游標(biāo)里主要包含兩種信息:SQL文本以及優(yōu)化目標(biāo)(optimizer goal),首次打開父游標(biāo)被鎖定,直到其他所有的session都關(guān)閉該游標(biāo)后才被解鎖。當(dāng)父游標(biāo)被鎖定的時(shí)候是不能被LRU算法置換出library cache,只有在解鎖以后才能置換出library cache,此時(shí)該父游標(biāo)對(duì)應(yīng)的所有子游標(biāo)也同樣被置換出library cache。v$sqlarea中的每一行代表了一個(gè)parent cursor,address表示其內(nèi)存地址。

子游標(biāo)在發(fā)生硬解析時(shí),在產(chǎn)生父游標(biāo)的同時(shí),則跟隨父游標(biāo)會(huì)產(chǎn)生相應(yīng)的子游標(biāo),此時(shí)V$SQL.CHILD_NUMBER的值為0。如果存在父游標(biāo),由于不同的運(yùn)行環(huán)境,此時(shí)同樣會(huì)產(chǎn)生新的子游標(biāo),新子游標(biāo)的CHILD_NUMBER在已有子游標(biāo)基礎(chǔ)上以1為單位累計(jì)。子游標(biāo)包括游標(biāo)所有相關(guān)信息,如具體的執(zhí)行計(jì)劃、綁定變、OBJECT、權(quán)限、優(yōu)化器設(shè)置等。子游標(biāo)隨時(shí)可以被LRU算法置換出library cache,當(dāng)子游標(biāo)被置換出library cache時(shí),oracle可以利用父游標(biāo)的信息重新構(gòu)建出一個(gè)子游標(biāo)來,這個(gè)過程叫reload。v$sql中的每一行表示了一個(gè)child cursor,根據(jù)hash value和address與parent cursor關(guān)聯(lián)。child cursor有自己的address,即v$sql.child_address。
確定一個(gè)游標(biāo)的三個(gè)主要字段:address、hash_value和child_number。sql_id可以唯一確定一個(gè)父游標(biāo),sql_id、child_number唯一確定一個(gè)子游標(biāo)。

session cursor生命周期:
session cursor需要從UGA中分配內(nèi)存,因此有其生命周期。其生命周期主要包括:
    打開游標(biāo)(根據(jù)游標(biāo)聲明的名稱在UGA中分配內(nèi)存區(qū)域);
    解析游標(biāo)(將SQL語句與游標(biāo)關(guān)聯(lián),并將其執(zhí)行計(jì)劃加載到Library Cache);
    定義輸出變量(僅當(dāng)游標(biāo)返回?cái)?shù)據(jù)時(shí));
    綁定輸入變量(如果與游標(biāo)關(guān)聯(lián)的SQL語句使用了綁定變量);
    執(zhí)行游標(biāo)(即執(zhí)行SQL語句);
    獲取游標(biāo)(即獲取SQL語句記錄結(jié)果,根據(jù)需要對(duì)記錄作相應(yīng)操作。游標(biāo)將逐條取出查詢的記錄,直到取完所有記錄);
    關(guān)閉游標(biāo)(釋放UGA中該游標(biāo)占有的相關(guān)資源,但Library Cache中的游標(biāo)的執(zhí)行計(jì)劃按LRU原則清除,為其游標(biāo)共享提供可能性);

對(duì)于session cursor而言,可以將游標(biāo)理解為任意的DML,DQL語句(個(gè)人理解,有待核實(shí))。即一條SQL語句實(shí)際上就是一個(gè)游標(biāo),只不過session cursor分為顯示游標(biāo)和隱式游標(biāo),以及游標(biāo)指針。由上面游標(biāo)的生命周期可知,任何的游標(biāo)(SQL語句)都必須經(jīng)歷內(nèi)存分配,解析,執(zhí)行與關(guān)閉的過程。故對(duì)隱式游標(biāo)而言,生命周期的所有過程由系統(tǒng)來自動(dòng)完成。對(duì)所有的DML和單行查詢(select ... into ...)而言,系統(tǒng)自動(dòng)使用隱式游標(biāo)。多行結(jié)果集的DQL則通常使用顯示游標(biāo)。

一個(gè)session cursor只能對(duì)應(yīng)一個(gè)shared cursor,而一個(gè)shared cursor卻可能同時(shí)對(duì)應(yīng)多個(gè)session cursor。

共享游標(biāo)舉例

假設(shè)有用戶SCOTT和KING,兩者均有表EMP。先以SCOTT為例,執(zhí)行如下語句:
select * from emp where empno = 7788;
SELECT * from emp where empno = 7788;
SELECT * FROM emp WHERE empno = 7788;
select * from emp where empno = 7788;

以上4條語句,第1條和第4條完全相同,第1條、第2條、第3條在大小寫上有不同,查詢v$sqlarea:
select sql_id, sql_text, executions
  from v$sqlarea
 where sql_text like '%empno = 7788%'
   and sql_text not like '%from v$sqlarea%';
  
執(zhí)行結(jié)果見下圖,有3條記錄,說明產(chǎn)生了3個(gè)父游標(biāo),其中一個(gè)父游標(biāo)執(zhí)行了2次。這說明,SQL語句必須完全一致(大小寫、空格回車等)才能共享,進(jìn)而避免硬解析。



這3個(gè)父游標(biāo)對(duì)應(yīng)的子游標(biāo)可以在v$sql中獲得:

select sql_id,
       hash_value,
       child_number,
       plan_hash_value,
       sql_text,
       executions
  from v$sql
 where sql_text like '%empno = 7788%'
   and sql_text not like '%from v$sql%';

執(zhí)行結(jié)果見下圖,可見生成父游標(biāo)時(shí)同時(shí)也生成一個(gè)以0為child_number的子游標(biāo),其sql_id和hash_value都和父游標(biāo)相同。



然后使用KING用戶,執(zhí)行相同的語句。然后查詢v$sqlarea父游標(biāo),結(jié)果仍然是3條記錄,不過執(zhí)行次數(shù)發(fā)生了變化:



再查詢子游標(biāo),結(jié)果是6條記錄,說明由于語句執(zhí)行的環(huán)境不同而造成生成不同的子游標(biāo):


產(chǎn)生子游標(biāo)的原因很多,比如上邊的用戶(SCHEMA)改變的例子,當(dāng)然還有很多其他原因也可以導(dǎo)致子游標(biāo)的產(chǎn)生,比如優(yōu)化器模式的改變,或者綁定變量的窺視等,如果你想確定是由那種原因造成的,需要查看v$sql_shared_cursor。

共享游標(biāo)其他知識(shí)點(diǎn)


    查看語句共享可以借助兩個(gè)數(shù)據(jù)字典:V$SQLAREA和V$SQL。V$SQLAREA保留SQL語句的父游標(biāo)信息,可以通過SQL_ID標(biāo)識(shí),其中的VERSION_COUNT列表示子游標(biāo)的數(shù)量。V$SQL保留SQL語句的子游標(biāo)信息,可以通過SQL_ID和CHILD_NUMBER標(biāo)識(shí)。V$SQL_SHARED_CURSOR可以查看語句產(chǎn)生子游標(biāo)的原因。
關(guān)于v$sql和v$sqlarea視圖字段及其詳解見“Oracle高資源消耗SQL語句定位”。

    父游標(biāo)的關(guān)鍵信息是sql文本,子游標(biāo)的關(guān)鍵信息是執(zhí)行計(jì)劃和執(zhí)行環(huán)境。
    硬解析通常是由于不可共享的父游標(biāo)造成的,如經(jīng)常變動(dòng)的SQL語句,或動(dòng)態(tài)SQL或未使用綁定變量等。
    解決硬解析的辦法則通常是使用綁定變量來解決。
    與父游標(biāo)SQL文本完全一致的情形下,多個(gè)相同的SQL語句可以共享一個(gè)父游標(biāo)。
    SQL文本、執(zhí)行環(huán)境完全一致的情形下,子游標(biāo)能夠被共享,否則如果執(zhí)行環(huán)境不一致則生成新的子游標(biāo)。
    游標(biāo)是可以被所有進(jìn)程共享的,也就是說如果100個(gè)進(jìn)程都執(zhí)行相同的SQL語句,那么這100個(gè)進(jìn)程都可以同時(shí)使用該SQL語句所產(chǎn)生的游標(biāo),從而節(jié)省了內(nèi)存。每個(gè)游標(biāo)都是由library cache中的兩個(gè)或多個(gè)對(duì)象所體現(xiàn)的,至少兩個(gè)對(duì)象:一個(gè)對(duì)象叫做父游標(biāo)(parent cursor),包含游標(biāo)的名稱以及其他獨(dú)立于提交用戶的信息,從v$sqlarea視圖里看到的都是有關(guān)父游標(biāo)的信息;另外一個(gè)或多個(gè)對(duì)象叫做子游標(biāo)(child cursors),如果SQL文本相同,但是可能提交SQL語句的用戶不同,或者用戶提交的SQL語句所涉及到的對(duì)象為同名詞等,都有可能生成不同的子游標(biāo)。因?yàn)檫@些SQL語句的文本雖然完全一樣,但是上下文環(huán)境卻不一樣,因此這樣的SQL語句不是一個(gè)可執(zhí)行的對(duì)象,必須細(xì)化為多個(gè)子游標(biāo)后才能夠執(zhí)行。子游標(biāo)含有執(zhí)行計(jì)劃或者PL/SQL對(duì)象的程序代碼塊等。

“Oracle共享游標(biāo)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

當(dāng)前標(biāo)題:Oracle共享游標(biāo)有哪些
網(wǎng)站網(wǎng)址:http://muchs.cn/article40/isjgho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航標(biāo)簽優(yōu)化、微信小程序響應(yīng)式網(wǎng)站、網(wǎng)站內(nèi)鏈網(wǎng)站策劃

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁設(shè)計(jì)