我有一个查询,如下所示:
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*/
,你可以看到这里是计划:
我对计划有一些疑问:
我希望在
operation-10
(operation-11
op-10 是 op-11 的子项)下,因为'IDX_CUSTNUM'
索引是针对'MI_DIMCUSTOMER'
table 的!看看op-5 and op-6
例子。或者op-8 and op-9
,我希望 op-10 和 op-11 完全像这两个一样,但不知道为什么不是!另一个问题是,查询中有两个连接,为什么我们
Nested loop joins
在计划中看到三个?每个嵌套循环的作用是什么?
提前致谢
您似乎为操作 ID 赋予了太多意义。它只是用来唯一标识每个操作,与操作执行的顺序无关。
您需要“从里到外”阅读计划,从最嵌套的操作到嵌套较少的操作。考虑到这一点,让我们看看发生了什么:
IDX1_SEGMENT
被扫描以检索ROWID
匹配该段的s。MI_SEGMENT_CUSTOMER_RELATION
读取from 的行ROWID
以过滤符合EFFECTIVE_DATE
条件的行并获取CUSTOMER_NUM
。CUSTOMER_NUM
值。IDX1_F
中扫描以查找与CUSTOMER_NUM
Op. 匹配的条目。5,并ROWID
检索到对应的s。MI_FACTCUSTOMER
读取from 的行ROWID
以过滤符合EFFECTIVE_DATE
条件的行并获取CUSTOMER_NUM
。CUSTOMER_NUM
来自 Op. 的值。8.IDX_CUSTOMER
fetch s。ROWID
ROWID
1.从 Op循环遍历s。10.MI_DIMCUSTOMER
中获取所需的列。显然,这些循环是同时执行的:只要来自 Op. 的新值。5 可用,是 Ops 的下一次迭代。9 和 8 可以继续,一旦完成,Ops 的下一次迭代。10 和 11 可以获取所需的数据。
鉴于行数较少且存在有用的索引,嵌套循环连接的选择似乎是合适的。