【问题标题】:Optimizing a multi join oracle query优化多连接 oracle 查询
【发布时间】:2021-12-11 02:03:43
【问题描述】:

我有以下 sql Oracle 查询,它可以正常工作,但在处理大量数据时有点慢。我查看了执行计划并使用了所有索引,但找不到进一步加快查询速度的方法:

 select n.ID_DOC as RECORDKEY,
        n.ID_TYPE_DOC as ID_TYPE_DOC,
        r.MN_TYPE_DOC as MN_TYPE_DOC,
        p.NUM_PLI as NUM_PLI,
        p.ID_ORIG as ID_ORIG 
        from DOCUMENT n 
        inner join CSFOLDITEM i on i.ITEMSUPPID = n.ID_DOC 
        inner join REF_TYPE_DOCUMENT r on r.ID_TYPE_DOC = n.ID_TYPE_DOC 
        inner join PLI p on P.ID_PLI = i.FOLDSUPPID 
        where n.ID_DOC in () ;
        

我尝试了以下另一种方法,但是成本相同,响应时间几乎相似:

select t1.ID_DOC,t1.ID_TYPE_DOC,t2.MN_TYPE_DOC,t3.NUM_PLI,t3.ID_ORIG from
            (select ID_DOC,ID_TYPE_DOC 
            from DOCUMENT where ID_DOC in ()) t1
           inner join
           (select ID_TYPE_DOC,MN_TYPE_DOC 
            from REF_TYPE_DOCUMENT ) t2
           ON (t1.ID_TYPE_DOC = t2.ID_TYPE_DOC)
          inner join
           (select c.ITEMSUPPID as ITEMSUPPID,p.NUM_PLI as NUM_PLI,p.ID_ORIG as ID_ORIG
            from PLI p inner join CSFOLDITEM c
            on p.ID_PLI = c.FOLDSUPPID) t3
           ON (t3.ITEMSUPPID = t1.ID_DOC) ;

关于我可以做些什么来获得更快的响应时间有什么建议吗?

IN子句中单条记录的第一次查询的执行计划:

【问题讨论】:

  • 你能用基数估计显示执行计划吗?我在您的图片中看不到任何基数估计。查询需要多长时间?
  • @RobertoHernandez 我添加了计划输出表,我不确定这是否是您要找的?
  • @mikeb,谢谢,这就是我想要的。但是,查询需要多少时间?
  • @RobertoHernandez 对于 IN 子句中的 400 条记录,最多可能需要 12 秒
  • 尝试在 sqlplus set autotrace traceonly 中运行它,然后使用 in 值运行查询。发布输出

标签: sql oracle inner-join


【解决方案1】:

在我看来,该计划看起来不错,但您可以使用更多索引来强调它,避免在这种情况下访问表。

让我解释一下我刚才说的话。您的计划在访问索引(INDEX UNIQUE SCANINDEX RANGE SCAN)后显示TABLE ACCESS BY ROWID。这意味着 Oracle 正在使用索引来查找包含数据的行,但它需要访问表,因为 select 包含一个或多个字段,这些字段不存在于索引中。

解决此问题的一种方法是创建新索引,因此 Oracle 只需访问它们即可恢复数据。例如

create index idx_document on document ( id_doc , id_type_doc ) ;

create index idx_ref_type_document on ref_type_document ( id_type_doc , mn_type_doc );

create index idx_pli on pli ( id_pli , id_orig, num_pli ) ;

但是,请记住,创建更多索引会提高查询性能,但会降低针对上述表的 DML 操作的性能。您需要评估是否值得。

另一个问题可能是估计基数,尝试使用 cascade => true 为查询中涉及的所有表收集统计信息,您也为所有索引收集。

【讨论】:

    猜你喜欢
    • 2019-05-12
    • 2020-04-30
    • 1970-01-01
    • 2020-01-02
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    相关资源
    最近更新 更多