在 "In" orperator 中使用子查询的 Oracle 性能问题
Oracle Performance issues on using subquery in an "In" orperator
我有两个看起来很相似的查询,但 Oracle 的性能却大不相同。
查询 A
Create Table T1 as Select * from FinalView1 where CustomerID in ('A0000001','A000002')
查询 B
Create Table T1 as Select * from FinalView1 where CustomerID in (select distinct CustomerID from CriteriaTable)
条件Table 有 800 行,但全部属于客户 ID 'A0000001' 和 'A000002'。
这意味着子查询:"select distinct CustomerID from CriteriaTable" also only returns the same two elements('A0000001','A000002') 在查询 A
中手动输入
以下是FinalView1下的查询
create or replace view FinalView1_20200716 as
select
Customer_ID,
<Some columns>
from
Table1_20200716 T1
INNER join Table2_20200716 T2 on
T1.Invoice_number = T2.Invoice_number
and
T1.line_id = T2.line_id
left join Table3_20200716 T3 on
T3.id = T1.Customer_ID
left join Table4_20200716 T4 on
T4.Shipping_ID = T1.Shipping_ID
left join Table5_20200716 Table5 on
Table5.Invoice_ID = T1.Invoice_ID
left join Table6_20200716 T6 on
T6.Shipping_ID = T4.Shipping_ID
left join First_Order first on
first.Shipping_ID = T1.Shipping_ID
;
Table1_20200716,Table2_20200716,Table3_20200716,Table4_20200716,Table5_20200716,Table6_20200716是对应table的浏览量具有时间有效性特征。例如
Table1_20200716下的查询
创建或替换视图 Table1_20200716 为
select
*
from Table1 as for period of to_date('20200716,'yyyymmdd')
然而 table “First_Order” 只是一个普通的 table as
以下是两个查询的性能(根据解释计划):
查询A:
基数:102
费用:204
总运行时间:最多 5 秒
查询 B:
基数:27921981
费用:14846
用户取消前总共 Runtime:20 分钟
所有 tables 都使用那些用于与 FinalView1 中的其他 tables 连接的列进行索引。根据explain plan,除了FirstOrdertable.
,其他都用过了
查询 A 在 FirstOrder Table 上使用了唯一索引,而查询 B 执行了完整扫描。
对于查询B,我原以为Oracle会先查询子查询,将结果放入in运算符,然后再执行主查询,因此对性能的影响应该很小。
提前致谢!
正如我 2 天前的评论中提到的。有人实际上 post 编辑了解决方案,然后在答案实际有效时将其删除。等了 2 天后,我设计了 post 那个解决方案。
该解决方案表明“in”运算符降低了性能。并建议我用内部连接替换它
Create Table T1 as
Select
FV.*
from
FinalView1 FV
inner join (
select distinct
CustomerID
from
CriteriaTable
) CT on CT.customerid = FV.customerID;
解释计划的结果比以前差:
Cardinality:28364465(来自 27921981)
成本:15060(从 14846)
然而,它只需要 17 秒。非常好!
我有两个看起来很相似的查询,但 Oracle 的性能却大不相同。
查询 A
Create Table T1 as Select * from FinalView1 where CustomerID in ('A0000001','A000002')
查询 B
Create Table T1 as Select * from FinalView1 where CustomerID in (select distinct CustomerID from CriteriaTable)
条件Table 有 800 行,但全部属于客户 ID 'A0000001' 和 'A000002'。 这意味着子查询:"select distinct CustomerID from CriteriaTable" also only returns the same two elements('A0000001','A000002') 在查询 A
中手动输入以下是FinalView1下的查询
create or replace view FinalView1_20200716 as
select
Customer_ID,
<Some columns>
from
Table1_20200716 T1
INNER join Table2_20200716 T2 on
T1.Invoice_number = T2.Invoice_number
and
T1.line_id = T2.line_id
left join Table3_20200716 T3 on
T3.id = T1.Customer_ID
left join Table4_20200716 T4 on
T4.Shipping_ID = T1.Shipping_ID
left join Table5_20200716 Table5 on
Table5.Invoice_ID = T1.Invoice_ID
left join Table6_20200716 T6 on
T6.Shipping_ID = T4.Shipping_ID
left join First_Order first on
first.Shipping_ID = T1.Shipping_ID
;
Table1_20200716,Table2_20200716,Table3_20200716,Table4_20200716,Table5_20200716,Table6_20200716是对应table的浏览量具有时间有效性特征。例如
Table1_20200716下的查询 创建或替换视图 Table1_20200716 为
select
*
from Table1 as for period of to_date('20200716,'yyyymmdd')
然而 table “First_Order” 只是一个普通的 table as
以下是两个查询的性能(根据解释计划):
查询A:
基数:102 费用:204
总运行时间:最多 5 秒
查询 B:
基数:27921981
费用:14846
用户取消前总共 Runtime:20 分钟
所有 tables 都使用那些用于与 FinalView1 中的其他 tables 连接的列进行索引。根据explain plan,除了FirstOrdertable.
,其他都用过了查询 A 在 FirstOrder Table 上使用了唯一索引,而查询 B 执行了完整扫描。
对于查询B,我原以为Oracle会先查询子查询,将结果放入in运算符,然后再执行主查询,因此对性能的影响应该很小。
提前致谢!
正如我 2 天前的评论中提到的。有人实际上 post 编辑了解决方案,然后在答案实际有效时将其删除。等了 2 天后,我设计了 post 那个解决方案。
该解决方案表明“in”运算符降低了性能。并建议我用内部连接替换它
Create Table T1 as
Select
FV.*
from
FinalView1 FV
inner join (
select distinct
CustomerID
from
CriteriaTable
) CT on CT.customerid = FV.customerID;
解释计划的结果比以前差: Cardinality:28364465(来自 27921981) 成本:15060(从 14846)
然而,它只需要 17 秒。非常好!