【问题标题】:Oracle mutliple left outer joins only max() rowsOracle 多个左外连接仅 max() 行
【发布时间】:2018-11-29 15:18:30
【问题描述】:

我有一个语句经常使用安静,但性能很差。 所以我想尽可能地优化它。该语句由各个部分和联合组成。

一个相当昂贵的部分如下。

select * 
from rc050 F
LEFT OUTER JOIN
    (SELECT fi_nr,
      fklz,
      rvc_status,
      lfdnr,
      txt
    FROM rc0531 temp
    WHERE lfdnr =
      (SELECT MAX(lfdnr) FROM rc0531 WHERE fi_nr = temp.fi_nr AND fklz = temp.fklz
      )
    ) SUB_TABLE1
  ON F.fklz   = SUB_TABLE1.fklz
  AND F.fi_nr = SUB_TABLE1.fi_nr
LEFT OUTER JOIN
    (SELECT fi_nr,
      fklz,
      rvc_status,
      lfdnr,
      txt
    FROM rc0532 temp
    WHERE lfdnr =
      (SELECT MAX(lfdnr) FROM rc0532 WHERE fi_nr = temp.fi_nr AND fklz = temp.fklz
      )
    ) SUB_TABLE2
  ON F.fklz   = SUB_TABLE2.fklz
  AND F.fi_nr = SUB_TABLE2.fi_nr
LEFT OUTER JOIN
    (SELECT fi_nr,
      fklz,
      rvc_status,
      lfdnr,
      txt
    FROM rc05311 temp
    WHERE lfdnr =
      (SELECT MAX(lfdnr)
      FROM rc05311
      WHERE fi_nr = temp.fi_nr
      AND fklz    = temp.fklz
      )
    ) SUB_TABLE11
  ON F.fklz   = SUB_TABLE11.fklz
  AND F.fi_nr = SUB_TABLE11.fi_nr
where F.fklz != ' '

这是我必须从这些 rc0531 ... rc05311 表中加载的部分 最新条目是什么。这些表中有 11 个,因此将其分解。 如您所见,我目前正在通过子查询加入每个表,并且只需要最新条目,因此我需要一个额外的子查询来获取 max(lfdnr)。

到目前为止,这一切都很好,但我想知道是否有更有效的方法来执行此操作。

在我的主选择中,我需要能够处理每个表中的每一列。

大家有什么建议吗?

目前在 13k 行上运行需要 1.3 秒才能获得不错的提升,这应该会降低到 0.1 秒左右。同样,这只是一个充满低效声明的更大声明中的一个问题。

【问题讨论】:

    标签: oracle join optimization subquery max


    【解决方案1】:

    无法优化 SQL 查询。 Oracle 将接受您的查询并确定一个执行计划,用于确定您所要求的信息。您可能会完全重写查询,如果它导致相同的执行计划,您将获得完全相同的性能。要调整查询,您需要确定 execution plan

    您可能会从每个表、(fi_nr, fklz) 列甚至(fi_nr, fklz, lfdnr) 上的索引中受益,具体取决于它的选择性。无法从这些信息中提前判断,您只需要尝试即可。

    您还应该删除select * 并仅选择您想要的列。如果可以从索引中获取所需的信息,Oracle 将不需要检索实际的表行。

    【讨论】:

    • 非常感谢。我已经在所有这些表上都有索引。我只选择需要的列。 select * 仅在此示例中。所以你告诉我,当它不需要整行而只需要部分行时,oracle 可以更快地交付?我认为它总是会加载整行。
    • 是的,如果它进入表,它将读取整行(好吧,块),但根据您的索引,它可能根本不需要从表中读取。如果我做了select id from mytable where id = 1,并且对 id 列进行了索引,它将对索引进行快速扫描,而根本不必从表中读取。
    【解决方案2】:

    替换左连接:

    LEFT OUTER JOIN (
        SELECT fi_nr,fklz,rvc_status,lfdnr,txt FROM rc0531 temp
        WHERE lfdnr = (SELECT MAX(lfdnr) FROM rc0531 WHERE fi_nr = temp.fi_nr AND fklz = temp.fklz)
        ) SUB_TABLE1
      ON F.fklz   = SUB_TABLE1.fklz
      AND F.fi_nr = SUB_TABLE1.fi_nr
    

    到这里:

    LEFT OUTER JOIN (
    
        SELECT fi_nr,fklz,rvc_status,lfdnr,txt FROM rc0531 inner join 
        (SELECT fi_nr, fklz, MAX(lfdnr) lfdnr FROM rc0531 group by fi_nr, fklz)x on x.fi_nr=rc0531.fi_nr and x.fklz=rc0531.fklz and x.lfdnr=rc0531.lfdnr
    
        ) SUB_TABLE1
      ON F.fklz   = SUB_TABLE1.fklz
      AND F.fi_nr = SUB_TABLE1.fi_nr
    

    如果它达到 0.1 秒,请告诉我,我想它会过去

    【讨论】:

      猜你喜欢
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      相关资源
      最近更新 更多