Oracle查询性能改进

时间:2018-09-08 11:29:37

标签: oracle performance indexing

我有两个具有以下结构的表

INPUTFILELOG ,列为

FILE_ID
RECORD_SEQ
ACCOUNT
CHILD_ACCOUNT

清除,列为

ACCOUNT
DATE
DETAILS

查询

delete from INPUTFILELOG il
where  exists
       ( select 1 from PURGE po
         where  po.account = ':NUMBER'
         and    ( po.account = il.account OR po.account = il.child_account ) )

即使在 PURGE.ACCOUNT INPUTFILELOG.ACCOUNT INPUTFILELOG.CHILD_ACCOUNT 上都有索引,上述查询的性能也很差。有人可以吗  请帮忙吗?

更新

我尝试了以下查询。看起来不错吗?有没有更好的方法来处理它?<​​/ p>

delete from INPUTLOG sif
where  exists
       ( select t.fileno, t.rec
         from   ( SELECT sif2.FILE_ID as fileno, sif2.RECORD_SEQ as rec
                  FROM   purge po 
                         INNER JOIN INPUTLOG sif2 
                              ON (   po.ACCOUNT = sif2.ACCOUNT
                                  OR po.ACCOUNT = sif2.CHILD_ACCOUNT )
                  where  po.account = ':NUMBER' ) t
         WHERE  sif.FILE_ID = t.FILEno
         AND    sif.record_seq = t.rec)

2 个答案:

答案 0 :(得分:1)

根据您的最新输入,我建议将原始查询分为以下两个查询,并验证它们在功能上是否正常(我认为应该如此)并验证其性能。我认为以下两个方法可能会更好,而这里的问题可能是由于“ OR OPERATOR”导致了全表扫描。

DELETE FROM INPUTLOG il
      WHERE EXISTS
               (SELECT 1
                  FROM PURGE po
                 WHERE po.account = ':NUMBER' AND (po.account = il.account))


DELETE FROM INPUTLOG il
      WHERE EXISTS
               (SELECT 1
                  FROM PURGE po
                 WHERE     po.account = ':NUMBER'
                       AND (po.account = il.child_account))

答案 1 :(得分:0)

您只想删除一个帐户。如果表中只有10个帐户,则全表扫描将是删除很大一部分表数据的最佳方法。但是您说,当您只删除帐户或子帐户时,删除要快得多。我认为这两次删除的总和时间比合并查询的总和要短得多。因此显然可以使用索引,这意味着它只能是要删除的表的很小一部分。

两个想法:

  1. 好吧,显然,您只需运行两个delete语句而不是一个,就可以实现您想要的功能。
  2. 非常清楚地显示DBMS,它只是您要从表INPUTFILELOG(由inputfilelog.account = ...删除)中删除的一个帐户。

因此:

delete from inputfilelog where account =
  (select account from purge where account = ':NUMBER');

delete from inputfilelog where child_account = 
  (select account from purge where account = ':NUMBER');

也许=甚至足以使组合的statemet快速运行(但通常不能将两个索引与OR组合使用)。

delete from inputfilelog
where account = (select account from purge where account = ':NUMBER')
or child_account = (select account from purge where account = ':NUMBER');

使用inputfilelog.account = ...的另一种方法:

delete from inputfilelog
where (account = :NUMBER or child_account = :NUMBER)
and exists (select * from purge where account = :NUMBER);