久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Oracle如何解讀執(zhí)行計劃

135次閱讀
沒有評論

共計 4834 個字符,預(yù)計需要花費 13 分鐘才能閱讀完成。

這篇文章給大家分享的是有關(guān) Oracle 如何解讀執(zhí)行計劃的內(nèi)容。丸趣 TV 小編覺得挺實用的,因此分享給大家做個參考,一起跟隨丸趣 TV 小編過來看看吧。

我先上一條語句,因為我覺得這條比較典型,所以我們就先用這條的執(zhí)行計劃來解讀下執(zhí)行計劃。
   

 

然后是這條 sql 的我調(diào)整過的一個執(zhí)行計劃,我們本文主要是看執(zhí)行計劃的部分。

執(zhí)行計劃的開頭

  首先不好意思,我把 sql_id,plan_hash_value 忘截圖了,基本上就是第一部分是執(zhí)行計劃的開頭,有 sql 文本,sqlid,plan hash value,child number,這就不贅述了。

執(zhí)行計劃的正文

  先說一下,這個正文的由來,為了能看到 starts,a-rows,a-time,buffers,0men,1mem… 所以,使用了:
alter sesssion set statistics_level=all;
select * from dbms_xplan.display_cursor(null,null, advanced allstat
所以說我們這次主要說的是以 dbms_xplan 包來看的執(zhí)行計劃內(nèi)容。

id,operation,name

      我們先籠統(tǒng)的介紹一下這個 3 個的意思跟由來。
     id:其實就是標(biāo)識每一個步步驟的一個序號,就是跟個身份證似的,這個是從 v$sql_plan 的 id 列中得到的,并不代表他們執(zhí)行的順序,不過我稍后就會說閱讀執(zhí)行計劃的順序及其原理。
     operation:是 v$sql_plan 中的 operation 列加上 option 列組合出來了,意思很淺顯,說的就是這一步的操作。
     name:就是 v$sql_plan 中的 object_name,也很明白,就是這一步操作的對象名稱。

      現(xiàn)在我們來解釋如果確定每一步的執(zhí)行順序。

      口訣隨便都能找到,就是看縮進,從左往右看,不對齊的,就是靠右的先執(zhí)行;到上下平行的或者說對齊的(緊挨著的),那靠上的就比靠下的先執(zhí)行,然后再繼續(xù)右看,看到最右邊的時候就完事兒。其實這個看不太明白我說的的,可以結(jié)合一下百度。
我直接說原理,當(dāng)然也不是最底層實現(xiàn)的原理,那個現(xiàn)在還搞不來。
      從左往右看,靠右的先執(zhí)行是因為,一個縮進就代表了一對父子,兒子把自己的步驟得到的結(jié)果集整理好,上交給老子,就這么一回事兒。所以說 0 - 8 的執(zhí)行順序是 8 7 6 5 4 3 2 1 0.(我這里又要道歉,我有點兒蠢了,沒給大家選到那種有倆個
緊挨著的兒子的執(zhí)行計劃,所以這里先說原理,大家這塊再結(jié)合下百度)
      然后當(dāng)你在找爹的路上往回走的時候,發(fā)現(xiàn)到了 id= 4 這一步,往下看發(fā)現(xiàn)了個叔叔 id=9,那這時候,4 和 9 是并列的,也就是同輩兒的,那就先不著急再往 3 走,而是先去看看 9 有沒有兒子,確實有一個,那按照靠右先執(zhí)行,應(yīng)該是 10 比 9 先執(zhí)行。
但是問題是,4 跟 9 誰先執(zhí)行呢?因為并列就是上面的先執(zhí)行,所以是 4 先執(zhí)行。然后又有人問了,那 9 跟 3 又是怎么個順序呀,9 跟 4 是兄弟,4 是 3 兒子,也就是說 9 也是 3 兒子,當(dāng)然是兒子先做收集結(jié)果集嘍。那現(xiàn)在得到的順序就成了 8-7-6-5-4-10-9-3-2-1-0。
      然而,當(dāng)找到 id= 3 得時候,又發(fā)現(xiàn),這個爸爸也有個同輩兒的,id=11,但是這個 11 沒正好就是個光棍兒,沒兒子。那就排出 3 比 11 先執(zhí)行。后面 2 1 0 都沒兄弟了,所以最終的執(zhí)行順序是 8 -7-6-5-4-10-9-3-11-2-1-0。
   
      這個說起來很枯燥,讀起來簡單其實,現(xiàn)在我就說下重點,這個到底是怎么個實現(xiàn)的。
      其實這就是個二叉樹,因為我第一次寫博客,很多沒考慮到,沒有把 v$sql_plan 中的 position 跟 parent_id,還有樹的深度截圖出來,很不好意思,所以口述下這倆個的圖形表現(xiàn)。就是他們在上面這張執(zhí)行計劃圖片表現(xiàn):同一個縮進度的就是 position 值
一樣的,只查一個縮進度的就是父子關(guān)系,也就是說 id= 3 和 id=11 的 parent_id 都是 2。
      現(xiàn)在我們來畫一下這個二叉樹,二叉樹就是只有倆個叉,所以你不可見到說誰不遵守計劃生育偏要整 3 個孩子的。

   

      看,每個塊塊里的數(shù)字就是 id。畫圖可以讓我們正著看執(zhí)行計劃,按 id 畫出來圖,然后再去理出執(zhí)行計劃的執(zhí)行順序。
      首先,第一個孩子都是往左邊畫,第二個孩子才是挨著往右邊畫,找其中典型的部分來說明下,3 下面的孩子是 4,但是發(fā)現(xiàn)僅比 3 少一個縮進的,或者說與 4 同縮進的還有 9。那先發(fā)現(xiàn)的 3 所以,3 畫左邊,9 畫右邊。而 9 下面的有 10,所以 10 畫 9 下面的左邊。
那有人問了,照這么說,10 跟 5 也是平行的,都比 4 少一個縮進,為啥不把 10 畫 4 下面,因為緊挨著的是直系,往上找沒有緊挨著的爸爸了才去找老王。所以就按照這個原則畫,就畫出了這個執(zhí)行計劃的本質(zhì)。
      然后,就是怎么遍歷這棵樹,后序遍歷,別問為什么。后序遍歷:先左后右再根。也就是說一直找到最左邊的節(jié)點(找到第一個緊挨著的并行的親兄弟的時候的最靠右的步驟,也就是這對親兄弟靠上的哥哥,執(zhí)行計劃的入口),然后往右找(這就是找親弟弟,這就是為啥靠上的先執(zhí)行),
沒有就往上找(找爹,縮進靠右的步驟先執(zhí)行的原因)。
      最后,我們來看上面這副圖,是不是 8 -7-6-5-4-10-9-3-11-2-1-0?!你要真不知道后序遍歷咋遍歷,你百度百科,賊簡單。

starts

    這個就是真實的這一個步驟的總的執(zhí)行次數(shù),你看上面所有步驟都只執(zhí)行了一次。

A-rows

      這個就是這一個步驟真實返回的行數(shù),actual rows。也就是說,最上面 id= 0 那一步的 a -rows 就是這條查詢最總返回來的行數(shù)。

A-time

      這一步真實執(zhí)行的時間。最上面 id= 0 那一步的 a -time 就是這條查詢的真實執(zhí)行時間。

buffers

  邏輯讀,這里沒顯示出 reads,但是還是說一下,reads 就是物理讀。

0mem,1mem

  這是說的 hash join,sort,group by 使用的 PGA 的內(nèi)存大小,具體我還沒驗證清楚,好像 0mem 是用的 PGA 內(nèi)存,1mem 是用的硬盤空間。

執(zhí)行計劃的 Qurey Block Name

 
  這里可能不太被大家注意,但是我覺得初學(xué),這里還是應(yīng)該看一看的。所謂查詢塊,說白了就是 select 的個數(shù)。這部分內(nèi)容,- 前面的數(shù)字是步驟 id。
      我在這里用 /*+ qb_name() */ 把查詢塊名固定了,就是方便自己閱讀,其實要是不用這個,oracle 會自己給查詢塊取名,而且也挺好懂的,都是以 SEL$ 開頭的,后面跟個數(shù)字。舉個例子,大家看 10 – 這一行,A@zong2,我們回執(zhí)行計劃找一找,id=10 走了一個索引。
你可能上來就看執(zhí)行計劃的時候會說,誒我去,這個索引是誰的呀。這不 qurey block 這部分就告訴你了嘛!這查詢塊 zong2 上的 a 表的。這個 zong2 我要是取名兒,oracle 會給它取名 SEL$2, 為啥?!因為簡單的說,這是第二個 select。
      希望初學(xué)者看這里的時候自己對著一行一行的回原計劃和原語句中找找。
      對了,這里我們發(fā)現(xiàn)一個在語句中并沒有的別名,from$_subquery$_007。我們回步驟 4 找一下,發(fā)現(xiàn)是 VIEW,再看看它是 qiurank1 塊兒的,那就很明白了,這個就是整個 qiurank1 這個子查詢整體的一個 view,說白了就是這么一整塊,它并不是一個真實存在再 oracle 中的視圖,
提醒大家一下,執(zhí)行計劃中別看見 view 就是視圖。子查詢不展開,也是被當(dāng) view 來對待的。
      綜上,我們是不是發(fā)現(xiàn),你從這部分內(nèi)容中,你可以發(fā)現(xiàn)具體操作的對象是誰的,是屬于那個 select 的?!
      好,但是這部分的用途到這里還不算完,我們接著往后看。

執(zhí)行計劃的 OUTLINE 部分

  是不是看到這個 /*+    */ 有點兒眼熟,沒錯,這就這條語句執(zhí)行使用的 hint,其實使用 hint 也就是來控制這部分。這部分其實是真的告訴你執(zhí)行計劃里面到底干了些什么,當(dāng)然,有一些我還不太確定,比如 merge(qba qbb),no_access, 這些目前就只能大致猜,原因很簡單,
因為我也是個初學(xué)者。
  那有人可能要問了,執(zhí)行計劃正文加上后面要介紹的謂詞條件,不就已經(jīng)告訴我們這條 sql 到底是怎么運作的嗎?還看這個干嘛。關(guān)鍵就是,一般我們?nèi)リP(guān)注執(zhí)行計劃,就是因為執(zhí)行計劃有問題了。所以,我們光知道執(zhí)行計劃是怎么個流程還不夠,我們是不是還要知道怎么修改它,讓
它按照我們理想的姿勢走正確的道路?!對于老司機,人家一眼就知道該加啥 hint,但是對于初學(xué)者,我們還是老老實實看看 outline,看看到底該加什么 hint,或者說該修改什么 hint。
  就這個圖片我舉個例子,看到倒數(shù)第三行,index_rs_asc 那一行,這一行明確告訴你有一步是走了索引,這一步就是走了 qiurank 塊里的 x 表的 … 索引,而且這個索引是 RS_ASC:range scan 升序的,說明走這個索引是正常從左往右走的而且還是個 index range scan。
      這一行下面,說了個啥?!是不是再說 qiurank 塊里的 x 表索引掃描完了,然后用 rowid 回表是用 batched 這種多塊掃描的方式回的表,自己可以去執(zhí)行計劃里面找找,就是 id=8,7 做的事情。還有往上看一行,leading 那一行,這個 hash join 的順序是不是跟執(zhí)行計劃里面體現(xiàn)的一毛一樣,
那我們把這里后面的做一個順序調(diào)整,然后加入到 sql 的 hint 當(dāng)中,就像這條 sql 的 hint 所做的那樣,是不是就能輕易的把 hash join 的順序進行調(diào)整,你說你調(diào)整 A 和 B 不用看這個 outline,那你調(diào)整子查詢那一整塊兒在 hash join 中的順序,你準(zhǔn)備咋調(diào)呀?!當(dāng)然,肯定有別的辦法,但是這樣做是不是
就很方便,后面你調(diào)整好這塊,然后在固定 profile 偷梁換柱的時候也方便呀。
      所以我覺得這里該好好了解,我還沒研究透,大家看到這篇文章的話,可以交流研討共同進步。

執(zhí)行計劃的 predicate information

 
      這個正經(jīng)沒啥可說的,就很直白。前面的數(shù)字還是 id,access 代表用了索引,意思就是進入這個索引塊跑了一圈兒。filter 才是真正的過濾條件,也就是說這是回了表以后在表上的過濾條件。自己對這執(zhí)行計劃一步一步的看。
    這里雖然很直白,但是很重要,如果你不看 outline 跟 qurey block 也就算了,這里你要是再不看,那讀執(zhí)行計劃其實還挺費勁的,因為你要把所有涉及的表的列和索引的基本信息放在旁邊,對著 sql 自己分析,就很累。而且有的時候,你覺得是這個索引走對了,比如說這條 sql 最后的條件,
你要是有一邊日期筆誤寫粗了,比如多加了個空格,出來的執(zhí)行計劃還是一毛一樣,但是 predicate information 就不一樣了。所以說,如果能看到這部分,還是要好好看一下。

執(zhí)行計劃的 column projection

      這里我還是好好說一下,雖然內(nèi)容不多,前面的數(shù)字還是 id,keys 就是說明這里有排序(這部分我后面學(xué)習(xí)明白了我再補充)。
      大拿不一定看這里,但是對于初學(xué)者,看一看是有收獲的。這部分就是每一個步驟操作的列以及該列的數(shù)據(jù)類型。道理很簡單,但是我們能學(xué)到一些東西,我們能通過這部分和執(zhí)行計劃正文了解到,每一步到底是在操作哪些列,我們看到你真正的排序操作,是在 8 7 6 一系列過濾后才開始在 5 進行
分析函數(shù)的排序,在完成最后的形成一個整體 view 之前,8 7 6 5 都是帶著 rowid 在操作的。
      反正看這里,就是能從另一個維度來看執(zhí)行計劃。還是希望初學(xué)者還是看一看,我覺得還是有收獲的。

執(zhí)行計劃的 note

   
      這不多說了,直接上個我總結(jié)的的圖,自己了解下吧。

Oracle 如何解讀執(zhí)行計劃

感謝各位的閱讀!關(guān)于“Oracle 如何解讀執(zhí)行計劃”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-07-20發(fā)表,共計4834字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 即墨市| 岑巩县| 永安市| 乐亭县| 河北区| 大连市| 哈密市| 南丹县| 安龙县| 江山市| 天祝| 石城县| 鄂托克旗| 江北区| 鄄城县| 札达县| 九台市| 合山市| 绥德县| 叶城县| 和林格尔县| 泰宁县| 通辽市| 锡林郭勒盟| 突泉县| 昔阳县| 盖州市| 河北省| 怀柔区| 株洲市| 垦利县| 龙南县| 临城县| 桃园县| 天柱县| 清水河县| 昌都县| 秭归县| 阿鲁科尔沁旗| 开原市| 肇庆市|