??????? 游標(biāo)是數(shù)據(jù)庫領(lǐng)域較為復(fù)雜的一個概念,因為游標(biāo)包含了shared cursor和session cursor。兩者有其不同的概念,也有不同的表現(xiàn)形式。
共享游標(biāo)的概念易于與SQL語句中定義的游標(biāo)相混淆。本文主要描述解析過程中的父游標(biāo),子游標(biāo)以及共享游標(biāo),即shared cursor,同時給出了
游標(biāo)(session cursor)的生命周期以及游標(biāo)的解析過程的描述。???
??????????? 有關(guān)游標(biāo)的定義,聲明,與使用請參考:
PL/SQL 游標(biāo)
??????????? 有關(guān)硬解析與軟解析請參考:
Oracle 硬解析與軟解析
一、相關(guān)定義
??????? shared cursor
??????????????? 也即是共享游標(biāo),是SQL語句在游標(biāo)解析階段生成獲得的,是位于library cache中的sql或匿名的pl/sql等。其元數(shù)據(jù)被在視圖V$sqlarea
??????????????? 與v$sql中具體化。如果library cache中的父游標(biāo)與子游標(biāo)能夠被共享,此時則為共享游標(biāo)。父游標(biāo)能夠共享即為共享的父游標(biāo),子游
??????????????? 標(biāo)能夠共享極為共享的子游標(biāo)。
???????????????
??????? session cursor
??????????????? 即通過系統(tǒng)為用戶分配緩沖區(qū)用于存放SQL語句的執(zhí)行結(jié)果。用戶可以通過這個中間緩沖區(qū)逐條取出游標(biāo)中的記錄并對其處理,直到所
??????????????? 有的游標(biāo)記錄被逐一處理完畢。session cursor指的跟這個session相對應(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視圖來具體化。每一
??????????????? 個打開或解析的SQL都將位于該視圖。
二、游標(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í)行計劃加載到Library Cache)
??????????????? 定義輸出變量(僅當(dāng)游標(biāo)返回數(shù)據(jù)時)
??????????????? 綁定輸入變量(如果與游標(biāo)關(guān)聯(lián)的SQL語句使用了綁定變量)
??????????????? 執(zhí)行游標(biāo)(即執(zhí)行SQL語句)
??????????????? 獲取游標(biāo)(即獲取SQL語句記錄結(jié)果,根據(jù)需要對記錄作相應(yīng)操作。游標(biāo)將逐條取出查詢的記錄,直到取完所有記錄)
??????????????? 關(guān)閉游標(biāo)(釋放UGA中該游標(biāo)占有的相關(guān)資源,但Library Cache中的游標(biāo)的執(zhí)行計劃按LRU原則清除,為其游標(biāo)共享提供可能性)
??????? 對于session cursor而言,可以將游標(biāo)理解為任意的DML,DQL語句(個人理解,有待核實)。即一條SQL語句實際上就是一個游標(biāo),只不過
??????? session cursor分為顯示游標(biāo)和隱式游標(biāo),以及游標(biāo)指針。由上面游標(biāo)的生命周期可知,任何的游標(biāo)(SQL語句)都必須經(jīng)歷內(nèi)存分配,解析,
??????? 執(zhí)行與關(guān)閉的過程。故對隱式游標(biāo)而言,生命周期的所有過程由系統(tǒng)來自動完成。對所有的DML和單行查詢(select ... into ...)而言,
??????? 系統(tǒng)自動使用隱式游標(biāo)。多行結(jié)果集的DQL則通常使用顯示游標(biāo)。
二、游標(biāo)的解析過程(產(chǎn)生shared cursor)
??????? 解析過程:
??????? A、包含vpd的約束條件:
??????????????? SQL語句如果使用的表使用了行級安全控制,安全策略生成的約束條件添加到where子句中
???????
??????? B、語法、語義、訪問權(quán)限檢查:
??????????????? 檢查SQL語句書寫的正確性,對象存在性,用戶的訪問權(quán)限
???????
??????? C、父游標(biāo)緩存:
??????????????? 將該游標(biāo)(SQL語句)的文本進(jìn)行哈希得到哈希值并在library cache尋找相同的哈希值,如不存在則生存父游標(biāo)且保存在library cache
??????????????? 中,按順序完成D-F步驟。如果此時存在父游標(biāo),則進(jìn)一步判斷是否存在子游標(biāo)。若存在相同的子游標(biāo),則直接調(diào)用其子游標(biāo)的執(zhí)行計
??????????????? 劃執(zhí)行該SQL語句,否則轉(zhuǎn)到步驟D進(jìn)行邏輯優(yōu)化???
???????
??????? D、邏輯優(yōu)化:
??????????????? 使用不同的轉(zhuǎn)換技巧,生成語義上等同的新的SQL語句(SQL語句的改寫),一旦該操作完成,則執(zhí)行計劃數(shù)量、搜索空間將會相應(yīng)增長。
??????????????? 其主要目的未進(jìn)行轉(zhuǎn)換的情況下是尋找無法被考慮到的執(zhí)行計劃
???????
??????? E、物理優(yōu)化:
??????????????? 為邏輯優(yōu)化階段的SQL語句產(chǎn)生執(zhí)行計劃,讀取數(shù)據(jù)字典中的統(tǒng)計信息以及動態(tài)采樣的統(tǒng)計信息,計算開銷,開銷最低的執(zhí)行計劃將被
??????????????? 選中。
???????????????
??????? F、子游標(biāo)緩存:
??????????????? 分配內(nèi)存,生成子游標(biāo)(即最佳執(zhí)行計劃),與父游標(biāo)關(guān)聯(lián)。可以在v$sqlarea, v$sql得到具體游標(biāo)信息,父子游標(biāo)通過sql_id關(guān)聯(lián)
???????
??????? 對于僅僅完成步驟A與B的SQL語句即為軟解析,否則即為硬解析
三、shared cursor與session cursor的關(guān)系以及軟軟解析
??????? 關(guān)系:???????
??????????????? 一個session cursor只能對應(yīng)一個shared cursor,而一個shared cursor卻可能同時對應(yīng)多個session cursor
四、父游標(biāo)與子游標(biāo)、共享游標(biāo)
??????? 由游標(biāo)的解析過程可知,父游標(biāo),子游標(biāo)同屬于共享游標(biāo)的范疇。
??????? 父游標(biāo)
??????????????? 是在進(jìn)行硬解析時產(chǎn)生的,父游標(biāo)里主要包含兩種信息:SQL文本以及優(yōu)化目標(biāo)(optimizer goal),首次打開父游標(biāo)被鎖定,直到其他
??????????????? 所有的session都關(guān)閉該游標(biāo)后才被解鎖。當(dāng)父游標(biāo)被鎖定的時候是不能被LRU算法置換出library cache,只有在解鎖以后才能置換出
??????????????? library cache,此時該父游標(biāo)對應(yīng)的所有子游標(biāo)也同樣被置換出library cache。v$sqlarea中的每一行代表了一個parent cursor,
??????????????? address表示其內(nèi)存地址。
???????????????
??????? 子游標(biāo)
??????????????? 當(dāng)發(fā)生硬解析時,在產(chǎn)生父游標(biāo)的同時,則跟隨父游標(biāo)會產(chǎn)生相應(yīng)的子游標(biāo),此時V$SQL.CHILD_NUMBER的值為0。
??????????????? 如果存在父游標(biāo),由于不同的運行環(huán)境,此時同樣會產(chǎn)生新的子游標(biāo),新子游標(biāo)的CHILD_NUMBER在已有子游標(biāo)基礎(chǔ)上以1為單位累計。
??????????????? 子游標(biāo)包括游標(biāo)所有相關(guān)信息,如具體的執(zhí)行計劃、綁定變量,OBJECT和權(quán)限,優(yōu)化器設(shè)置等。子游標(biāo)隨時可以被LRU算法置換出
??????????????? library cache,當(dāng)子游標(biāo)被置換出library cache時,oracle可以利用父游標(biāo)的信息重新構(gòu)建出一個子游標(biāo)來,這個過程叫reload。
??????????????? v$sql中中 的每一行表示了一個child cursor,根據(jù)hash value和address與parent cursor 關(guān)聯(lián)。
??????????????? child cursor有自己的address,即v$sql.child_address。
??????? 確定一個游標(biāo)的三個主要字段:address,hash_value,child_number,
五、演示父游標(biāo)、子游標(biāo)?? ?????
六、總結(jié)
??????? 1、硬解析通常是由于不可共享的父游標(biāo)造成的,如經(jīng)常變動的SQL語句,或動態(tài)SQL或未使用綁定變量等
??????? 2、解決硬解析的辦法則通常是使用綁定變量來解決
??????? 3、與父游標(biāo)SQL文本完全一致的情形下,多個相同的SQL語句可以共享一個父游標(biāo)
??????? 4、SQL文本、執(zhí)行環(huán)境完全一致的情形下,子游標(biāo)能夠被共享,否則如果執(zhí)行環(huán)境不一致則生成新的子游標(biāo)
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
