Улучшение производительности Oracle Query - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть две таблицы с приведенной ниже структурой

INPUTFILELOG со столбцами как

FILE_ID
RECORD_SEQ
ACCOUNT
CHILD_ACCOUNT

PURGE с колонкой

ACCOUNT
DATE
DETAILS

QUERY

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 . Может кто то пожалуйста помогите?

UPDATE

Я попробовал следующий запрос. Это выглядит хорошо? Есть ли лучший способ справиться с этим?

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 голосов
/ 08 сентября 2018

Вы хотите удалить только одну учетную запись. Если бы в таблице было, скажем, только десять учетных записей, то полное сканирование таблицы было бы лучшим способом удалить этот большой процент данных таблицы. Но вы говорите, что удаление происходит намного быстрее, когда вы удаляете только учетные записи или дочерние учетные записи. Я понял, что время сложения двух удалений намного короче, чем у вашего комбинированного запроса. Очевидно, что тогда используется индекс, а это означает, что он должен быть только очень небольшим процентом удаляемой таблицы.

Две идеи:

  1. Ну, очевидно, вы можете просто запустить два оператора удаления вместо одного и достичь того, чего хотите.
  2. Четко показать СУБД, что из таблицы нужно удалить только одну учетную запись 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');

Может быть, = достаточно даже для быстрого выполнения комбинированного мета состояния (но использование двух индексов в сочетании с 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);
0 голосов
/ 08 сентября 2018

Исходя из ваших последних данных, я хотел бы предложить разбить оригинальный запрос на следующие два запроса и проверить, в порядке ли они функционально (как мне кажется, это должно быть), и проверить их производительность. Я думаю, что следующие два могут работать лучше, и проблема здесь может быть из-за «ИЛИ ОПЕРАТОРА», который приводит к полному сканированию таблицы.

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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...