Oracle

儘管在主查詢中使用了兩個內部聯接,但執行計劃中的三個“嵌套循環聯接”

  • January 9, 2022

我有一個查詢,如下所示:

with cte as
(select customer_num
   from vmi_segment_customer_relation
  where effective_date = to_date('12/30/2021', 'mm/dd/yyyy')
    and segment_id = 10000000592
    )
select 
t.customer_num, 
cust_first_name, 
cust_last_name, 
cust_type_desc
 from vmi_factcustomer t
 join cte f
   on t.customer_num = f.customer_num
  and t.effective_date = to_date('12/30/2021', 'mm/dd/yyyy')

 join vmi_dimcustomer d
   on t.customer_num = d.customer_num;

如您所見,此查詢中有三個表

  1. vmi_segment_customer_relation、索引:"IDX1_SEGMENT""segment_id" 列上。

  2. vmi_factcustomer、索引:"IDX1_F""customer_num" 列上。

  3. vmi_dimcustomer、索引:"IDX_CUSTNUM""customer_num"列上。

所有表statistics都是最新的,並且沒有過時的統計資訊。我execution plan使用這個提示得到了這個查詢的真實資訊/*+gather_plan_statistics*/,你可以看到這裡是計劃:

在此處輸入圖像描述

我對計劃有一些疑問:

  1. 我希望在operation-10operation-11op-10 是 op-11 的子項)下,因為'IDX_CUSTNUM'索引是針對'MI_DIMCUSTOMER'table 的!看看op-5 and op-6例子。或者op-8 and op-9,我希望 op-10 和 op-11 完全像這兩個一樣,但不知道為什麼不是!
  2. 另一個問題是,查詢中有兩個連接,為什麼我們Nested loop joins在計劃中看到三個?每個嵌套循環的作用是什麼?

提前致謝

您似乎為操作 ID 賦予了太多意義。它只是用來唯一標識每個操作,與操作執行的順序無關。

您需要“從裡到外”閱讀計劃,從最嵌套的操作到嵌套較少的操作。考慮到這一點,讓我們看看發生了什麼:

  • 作品。6.IDX1_SEGMENT被掃描以檢索ROWID匹配該段的s。
  • 作品。5.MI_SEGMENT_CUSTOMER_RELATION讀取from 的行ROWID以過濾符合EFFECTIVE_DATE條件的行並獲取CUSTOMER_NUM
  • 作品。3. 循環檢索到的CUSTOMER_NUM值。
  • 作品。9. 在循環IDX1_F中掃描以查找與CUSTOMER_NUMOp. 匹配的條目。5,並ROWID檢索到對應的s。
  • 作品。8.MI_FACTCUSTOMER讀取from 的行ROWID以過濾符合EFFECTIVE_DATE條件的行並獲取CUSTOMER_NUM
  • 作品。2. 循環CUSTOMER_NUM來自 Op. 的值。8.
  • 作品。10. 在循環中訪問匹配客戶編號的IDX_CUSTOMERfetch s。ROWID
  • 在。ROWID1.從 Op走過s。10.
  • 作品。11. 在循環訪問MI_DIMCUSTOMER中獲取所需的列。

顯然,這些循環是同時執行的:只要來自 Op. 的新值。5 可用,是 Ops 的下一次迭代。9 和 8 可以繼續,一旦完成,Ops 的下一次迭代。10 和 11 可以獲取所需的數據。

鑑於行數較少且存在有用的索引,嵌套循環連接的選擇似乎是合適的。

引用自:https://dba.stackexchange.com/questions/305852