-1

我有两个查询看起来很接近,但 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)

CriteriaTable 有 800 行,但都属于客户 ID 'A0000001' 和 'A000002'。这意味着子查询:“select distinct CustomerID from CriteriaTable”也只返回与查询 A 中手动输入的相同的两个元素('A0000001'、'A000002')

以下是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 是具有时间有效性特征的对应表的视图。例如

Table1_20200716下的查询创建或替换视图Table1_20200716为

select
*
from Table1 as for period of to_date('20200716,'yyyymmdd')

但是表“First_Order”只是一个普通表

以下是两个查询的性能(根据解释计划):

查询一:

基数:102 成本:204

总运行时间:最长 5 秒

查询 B:

基数:27921981

费用:14846

总运行时间:20 分钟直到用户取消

所有表都使用那些用于连接 FinalView1 中其他表的列进行索引。根据说明计划,除了FirstOrder 表之外,它们都已被使用。

查询 A 使用 FirstOrder 表上的唯一索引,而查询 B 执行完整扫描。

对于查询 B,我期望 Oracle 会在执行主查询之前先查询子查询将结果放入 in 运算符,因此对性能的影响应该很小。

提前致谢!

4

1 回答 1

0

正如我两天前的评论所述。有人实际上已经发布了解决方案,然后在答案实际有效时将其删除。等待 2 天后,所以我设计发布该解决方案。

该解决方案表明“in”运算符降低了性能。并建议我用内部连接替换它

Create Table T1 as 
Select 
    FV.* 
from 
    FinalView1 FV 
    inner join (
        select distinct 
            CustomerID 
        from 
            CriteriaTable
    ) CT on CT.customerid = FV.customerID;

解释计划的结果比以前更糟:基数:28364465(来自 27921981)成本:15060(来自 14846)

但是,它只需要 17 秒。这是非常好的!

于 2020-07-19T22:48:49.043 回答