10 巢狀迴圈(NESTED LOOP)--優化主題系列
Oracle從較小結果集(驅動表/外部表)中讀取一行,然後和較大結果集(被探查表/內部表)中的所有資料逐條進行比較(巢狀迴圈可以用於非等值連線),如果符合規則,就放入結果集中,然後取較小結果集的下一條資料繼續進行迴圈,直到結束。巢狀迴圈只適合輸出少量結果集或者是用於快速輸出結果集。
conn scott/tiger
alter session set statistics_level=all;
select e.ename,e.job,d.dname from emp e,dept d wheree.deptno=d.deptno and e.sal<2000;
select * fromtable(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
NESTED LOOPS表示巢狀迴圈,Starts表示某個操作執行的次數,那麼這裡巢狀迴圈操作一共執行了1次,EMP表離NESTEDLOOPS最近,表示EMP表作為驅動表,它執行了1次(全表掃描)返回了8條記錄。Oracle這時候就會從這8條記錄中讀取一行,然後去匹配內部表,因為驅動表返回了8條記錄,所以內部迴圈會執行8次。
提問:巢狀迴圈的執行計劃中那個表是驅動表??驅動表返回10W條資料,被驅動表要掃描10W次對吧??
被驅動表走索引至少讀多少個塊?假設索引高度是3 即(3+1)*10W=40W是不是要進行 40W 次物理I/O
提問:為什麼巢狀迴圈驅動表必須是返回結果集很少??
SQL優化的核心思想是什麼??
提問:為什麼巢狀迴圈被驅動表上面一定要有索引??
假設驅動表返回5000條資料要是被驅動表沒索引假設被驅動表有1GB大小是不是5000次的全表掃描??掃描5T??
提問:執行計劃中一大串巢狀迴圈套巢狀迴圈怎麼辦??
是不是要看最裡面的巢狀迴圈走錯了 I/O扛不住的
比如說驅動表返回10W條結果你敢走NL嗎??是不是要進行10W次I/O掃描??
提問:當看到一個執行計劃中有巢狀迴圈首先應該檢查哪裡??
直接 SELECTCOUNT(*) FROM 驅動表where 過濾條件.....
你去查詢發現 NL 的驅動表返回 10W 行
但是執行計劃的ROWS 只返回 500行
統計資訊有問題
假設統計資訊沒問題
提問:驅動表有2GB大小適合做驅動表嗎??
驅動表大不大並不關心關心的是返回行數
如果返回行數太大是不是走NL就錯了??應該走HASH連線對吧
假設有一個表100W條資料它作為驅動表返回20W條資料那麼它的執行計劃是對的嗎??
假設驅動表返回1條資料被驅動表返回10W條資料最終返回10W條資料對不對??
被驅動表走索引並且返回10W條結果會快嗎??
假設索引塊一個塊儲存100條記錄要讀10W/100=1000次
提問:被驅動表的索引建立在哪個列上面?被驅動表上面有過濾條件where 條件在前面還是 JOIN 條件在前面?
巢狀迴圈裡面被驅動表千萬不能全表掃描一定要走索引而且索引要建立在join列上
如果是組合索引那麼join列不要作為引導列
被驅動表的索引列選擇性要高這樣聚簇因子影響有限
join列最好是主鍵如果join列資料不均衡而且聚簇因子很高走索引很坑
巢狀迴圈無需等到所有操作執行完畢才返回結果,它只需要迴圈匹配上就可以返回結果。如果某個查詢返回的結果小於等於驅動表的10%,那麼Oracle很有可能選擇巢狀迴圈來處理資料。在巢狀迴圈中,驅動表/外部表一般很小(這樣利用全表掃描),或者是表比較大,然後利用高度可選的索引過濾大量資料,得到結果集(這個結果集一般小於源表10%)來作為驅動表,被驅動表/內部表通常較大,而且在連線列上面建立唯一索引/或者高度可選的非唯一索引(如果被驅動表/內部表上面缺乏索引,CBO通常會選擇雜湊連線)。
為什麼要用小表/結果集較小的表作為驅動表??
因為如果表/結果集很大,那麼返回的資料就多了,這樣迴圈次數就會增加,會導致多次indexunique/range scan,那麼效率就下去了,這個時候CBO會考慮交換驅動表或者乾脆選擇雜湊連線。
為什麼內部表的連線列上面要有索引??
因為如果內部表很大,如果連線列上面沒有索引,那麼會導致Oracle對內部表進行全表掃描,而且是多次(根據外部表返回記錄數),這樣效率極其低下,所以如果內部表的連線列上面沒有索引,CBO會選擇雜湊連線。
如何識別錯誤的nestedloop??
1. 可以通過比較E-Rows和A-Rows,如果兩者相差太大,說明執行計劃出問題了。這種方法適合OLTP系統。
2. 如果是OLAP,可以人工計算驅動表返回行數,然後比較CBO計算的返回行數,如果兩者相差太大,說明執行計劃出了問題。
3. 除了檢視驅動表之外,我們還要檢視被驅動表。被驅動表上面的連線列上通常有唯一索引或者高度可選的非唯一性索引,如果你看到被驅動表走了bitmapindex,那麼你要注意了。另外被驅動表也可能是走的fulltable scan,這個時候我們要selectcount(*)然後比較CBO計算的值,如果2者相差太大,說明執行計劃有問題,當然也說明統計資訊有問題。
一般執行計劃的 ROWS 要算少
ID=49 返回多少行?
它是不是回收站?
HASH JOIN 之後是不是作為NL 驅動表
返回 354K 條資料
X$KTFBUE (ind:1)
那麼這個要被掃描 354K 這麼多次
ID=80 這裡也有回收站
78 這裡又是 NL
79 的HASH JOIN 結果集又作為驅動表
是不是有些基表要被掃描100W次?
ID=47 是不是NL???
48 是不是作為NL 的驅動表
48 是不是返回30多W行?
51 是不是與 HASHJOIN 平級?
ID=51 是不是要被掃描30W次?
執行計劃裡面估算一般算少
那麼是不是資料字典要被掃描上百萬次???
如果某個塊連續的被掃描上百萬次
是不是熱點塊?
latch: cache buffers chains
現在搞懂了沒
系統的熱點塊怎麼產生的?
一個系統中熱點塊怎麼產生的??
99% 都是SQL 效能問題而且 99% 都是錯誤的 NL 引起的
某個塊要被一個latch保護
這個 latch 有可能保護另外的塊
那麼其他SESSION 要來訪問這個latch 保護的另外的塊是不是又遇到競爭了?
一般一個 latch 只管幾十個到幾百個塊
某個系統db filesequential read 排名TOP 1 這個系統一般是什麼問題?
比如說某個系統有大批量的 DML 如果沒禁止索引那麼上面的等待事件也會排名第一
用一句話來總結驅動表返回1行被驅動表掃描一次
SQL 優化的核心思想就是減少物理IO 掃描次數相關推薦
10 巢狀迴圈(NESTED LOOP)--優化主題系列
Oracle從較小結果集(驅動表/外部表)中讀取一行,然後和較大結果集(被探查表/內部表)中的所有資料逐條進行比較(巢狀迴圈可以用於非等值連線),如果符合規則,就放入結果集中,然後取較小結果集的下一條
oracle 表連線方式: nested loop 巢狀迴圈和Hash Join的比較
一、建立兩張實驗用表:wireless_site.merchant和wireless_site.bb SQL> select count(*) from wireless_site.merchant; COUNT(*) ---------- 14005
圖解Oracle 表連線優化之巢狀迴圈連線(Nested loops join)
當一條SQL語句引用多張表連線時,Oracle的查詢優化器(Optimizer)不僅要確定每張表的訪問路徑,而且需要確定這些表的連線順序和連線方法。查詢優化器的目標是通過儘早地過濾不需要的資料,減少需要處理的資料量。 Oracle的SQL優化器(Optimizer)在執行
加快LOOP巢狀迴圈的一個方法
LOOP AT it_mara. LOOP AT it_marc WHERE matnr = it_mara . * 處理程式碼 WRITE: AT /1 it_marc-matnr, it_marc-werks. ENDLOOP.
Oracle表連線操作——Nest Loop Join(巢狀迴圈)
關係型資料庫並不是最早出現的資料庫表現形式,之前還存在層次、網狀資料庫結構。隨著關係型資料庫的出現,以資料表的方式進行資訊留存的方案迅速發展起來。關係型資料庫的重要元素包括資料表和表連線,藉助各種型別的表連線,可以將平鋪直敘的資訊加以組裝拼接。在Oracle資料庫中,應對不同
C++中for迴圈巢狀遍歷的優化方法
專案開發過程中經常會出現A集合與B集合中資料對比取相同資料的情況。 最簡單的實現方法如下: //List<T> A = new ArrayList<T>(); //List<T> B = new ArrayList<T>(
10. C語言 -- 迴圈結構:for 語句和巢狀迴圈
本部落格主要內容為 “小甲魚” 視訊課程《帶你學C帶你飛》【第一季】 學習筆記,文章的主題內容均來自該課程,在這裡僅作學習交流。在文章中可能出現一些錯誤或者不準確的地方,如發現請積極指出,十分感謝。 也歡迎大家一起討論交流,如果你覺得這篇文章對你有所幫助,記得
小程式二次迴圈,巢狀迴圈
巢狀迴圈 test.wxml <view wx:for="{{test}}" wx:key="" class='onearr'> <view>姓名:{{item.name}}</view> <view>學校:{{ite
Linux Shell程式設計 17 巢狀迴圈
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
微信小程式的巢狀迴圈
微信小程式的巢狀迴圈 聽說最近微信小程式開發火熱,不久前做了一個小程式測試,由於要取日期及下面資料。迴圈巢狀還是搞了又好一會兒。 下面是程式碼: 資料: var DateShow=[ [{name:111},{name:666},{name:555},{name:333}]
巢狀迴圈概念
巢狀迴圈:迴圈體中還可以宣告迴圈,相當於內層迴圈的整體充當外層迴圈的迴圈體例:for(;;){ for(;;){ }}或者while(){ for(;;){ }}題目:輸出四排*,要求用巢狀迴圈********** public class V{ public static void
while,for 迴圈輸出九九乘法表,使用python 巢狀迴圈
while迴圈: i=1 while i<=9: j=1 while j<=i: print('%d*%d=%d'%(j,i,i*j),end='\t') # \t 可以使其上下對齊 j+=1 print('\n')
微信小程式 巢狀迴圈
前言 入門教程之列表渲染多層巢狀迴圈,目前官方的文件裡,主要是一維陣列列表渲染的案例,還是比較簡單單一,給剛入門的童鞋還是無從入手的感覺。 <view wx:for="{{items}}"> {{index}}: {{item.message}} </view> 還有一個九
高效遍歷匹配Json資料,避免巢狀迴圈
工作中經常會遇到這樣的需求:1.購物車列表中勾選某些,點選任意一項,前往詳情頁,再返回購物車依舊需要呈現勾選狀態2.勾選人員後,前往別的頁面,再次返回,人員依舊程勾選狀態3.等等.... 資料結構如下: // 快取資料 var students = [
php中用for巢狀迴圈解決雞兔同籠問題
上課老師佈置的任務 原始碼: --------------------------------------------------------------------------------------------------------------------
在Java中,如何跳出當前的多重巢狀迴圈?
在Java中,要想跳出多重迴圈,可以在外面的迴圈語句前定義一個標號,然後在裡層迴圈體的程式碼中使用帶有標號的break 語句,即可跳出外層迴圈。例如: 另外,我個人通常並不使用標號這種方式,而是讓外層的迴圈條件表示式的結果可以受到裡層迴圈體程式碼的控制,例如,要在二維陣列中查詢到某個數字。
你需知道的java如何跳出巢狀迴圈
使用 迴圈標籤,程式碼如下: public static void main(String[] args){ lableB: for(int i=0;i<3;i++){ lableA: for(int j=0;j<
oracle 在儲存過程中寫兩個遊標巢狀迴圈
CREATE OR REPLACE PROCEDURE "PROC_CHZBANKMOTNREC" AS vid NUMBER(19);--id vzdrpriaccount VARCHAR2(1
使用巢狀迴圈列印圖形
迴圈巢狀 迴圈裡面可以巢狀迴圈,今天我們就用雙層for迴圈列印圖形和做出楊輝三角。列印圖形時,把圖形看做行,列。外層迴圈來控制行,內層控制列。如果是有星星還有空格的型別。模板就是 外層 for(int i = 0;i<=行數;i++) 內
for巢狀迴圈
巢狀迴圈是指在一個迴圈內包含另一個迴圈,巢狀迴圈常用於按行和列顯示資料,也就是說,一個迴圈處理一行中的所有列,另一個迴圈處理所有的行。 for迴圈巢狀簡單來說就是一個外圈的for程式裡面一個套著一個小的for程式, 例如9*9乘法口訣表 : #include