сравнивая два курсора в oracle вместо использования MINUS - PullRequest
0 голосов
/ 23 марта 2010

Выполнение следующего запроса занимает более 3 минут, поскольку таблицы содержат большие объемы данных:

  SELECT  RTRIM(LTRIM(A.HEAD)),
      A.EFFECTIVE_DATE,
    FROM   TABLE_1 A
    WHERE  A.TYPE_OF_ACTION='6'
    AND    A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15)  

    MINUS

    SELECT  RTRIM(LTRIM(B.head)),
      B.EFFECTIVE_DATE,
    FROM  TABLE_2 B

В нашей системе запрос уничтожается, если он выполняется более 8 секунд. Есть ли способ выполнить запросы по отдельности ... ввести их в cursors..compare и затем получить результаты? таким образом, каждый запрос будет выполняться индивидуально, а не как один массивный запрос, который занимает 3 минуты.

Как бы сравнить два курсора с имитирующими MINUS?

Ответы [ 2 ]

1 голос
/ 23 марта 2010

МИНУС - это заданная операция, которая, так же как и удаление результатов второго запроса от первого, также удалит дубликаты, если они появятся в первом наборе. Таким образом, показанный запрос всегда должен будет построить полный набор результатов из TABLE_1, прежде чем возвращать его пользователю.

Если вы можете быть уверены, что в первом наборе нет дубликатов заголовка / даты вступления в силу (или вы не хотите, чтобы такие дубликаты были удалены), вы можете попробовать

SELECT  RTRIM(LTRIM(A.HEAD)), A.EFFECTIVE_DATE,
    FROM   TABLE_1 A
    WHERE  A.TYPE_OF_ACTION='6'
    AND    A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15)
    AND NOT EXISTS 
         (select 1 from table_2 b 
          where RTRIM(LTRIM(b.head)) = RTRIM(LTRIM(a.head))
          and b.effective_date = a.effective_date) )

Таким образом, запрос может начать возвращать результаты намного быстрее, особенно если table_2 очень мал или доступ к строкам возможен через индекс эффективное_даты или заголовок.

PS. Если вы можете, удалите биты RTRIM (LTRIM ()).

PPS. Там все еще нет гарантии, что он вернется менее чем за 8 секунд. Это будет зависеть от того, насколько большой table_1, и индексов для type_of_action и / илиffective_date.

Добавлено:

Вы можете навести курсор на

SELECT  RTRIM(LTRIM(A.HEAD)), A.EFFECTIVE_DATE,
    FROM   TABLE_1 A
    WHERE  A.TYPE_OF_ACTION='6'
    AND    A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15)

и игнорировать строки, если он вернул

    select 1 from table_2 b 
      where RTRIM(LTRIM(b.head)) = :1
      and b.effective_date = :1
      and rownum =1

Но, безусловно, потребуется больше времени, чтобы полностью выполнить. Возможно, на несколько порядков больше (т. Е. Часов), в зависимости от того, сколько времени занимает проверка table_2. Не совсем точно, какие критерии используются для обрезания (длительность вызова или длительность открытого курсора SQL), поэтому он может закрыть внешний курсор. И в зависимости от размера / индекса / содержимого таблицы_1 внешний курсор может все еще не возвращать первые строки в пределах таймфрейма.

Сколько строк в table_1, table_2 и какие индексы доступны?

0 голосов
/ 23 марта 2010

МИНУС - это то же самое, что сказать: «получить все строки первого запроса, затем из этого набора удалить строки, которые также находятся во втором запросе», так что вы можете загрузить результаты первого запроса в массив в -Memory, затем переберите результаты второго запроса, проверьте их по одному на соответствие результатам первого запроса и удалите их, если они существуют.

Я не уверен, что на самом деле будет лучше, хотя (зависит от многих вещей). Вы также можете рассмотреть возможность использования NOT EXISTS вместо этого и проверить эту производительность, т.е.

SELECT  RTRIM(LTRIM(A.HEAD)),
  A.EFFECTIVE_DATE,
FROM   TABLE_1 A
WHERE  A.TYPE_OF_ACTION='6'
AND    A.EFFECTIVE_DATE >= ADD_MONTHS(SYSDATE,-15)  
AND NOT EXISTS (
  SELECT 1 fFROM TABLE_2 B
  WHERE RTRIM(LTRIM(A.HEAD)) = RTRIM(LTRIM(B.HEAD))
  AND A.EFFECTIVE_DATE = B.EFFECTIVE_DATE
)

Некоторое функциональное индексирование также может потребоваться для RTRIM (LTRIM (A.HEAD))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...