Оптимизировать длительный запрос на выборку по базе данных Oracle - PullRequest
0 голосов
/ 02 июня 2018

Я не эксперт по БД, у нас есть запрос Oracle для извлечения данных за определенный день, проблема в том, что если объем бизнеса за день чрезвычайно велик, запрос занимает более 8 часов и время ожидания,Мы не можем провести оптимизацию внутри самой базы данных, тогда как мы обычно справляемся с такими экстремальными случаями?Я вставил запрос ниже с содержимым, замаскированным, чтобы показать структуру SQL, и искал советы о том, как оптимизировать этот запрос или любой другой альтернативный способ избежать тайм-аута.

WHENEVER SQLERROR EXIT 1
SET LINESIZE 9999
SET ECHO OFF
SET FEEDBACK OFF
SET PAGESIZE 0
SET HEADING OFF
SET TRIMSPOOL ON
SET COLSEP ","

SELECT co.cid
  || ',' || DECODE(co.cid,'xxxxx','xxxx',null,'N/A','xxxxx')
  || ',' || d.name
  || ',' || ti.rc
  || ',' || DECODE(cf.side_id,1,'x',2,'xx',5,'xx','')
  || ',' || cf.Quantity
  || ',' || cf.price
  || ',' || TO_CHAR(time,'YYYY-mm-dd hh24:mi:ss')
  || ',' || DECODE(co.capacity_id,1,'xxxx',2,'xxxx','')
  || ',' || co.type
  || ',' || cf.id
  || ',' || CASE
              WHEN (cf.account_id = xxx OR cf.account_id = xxx) THEN SUBSTR(cf.tag, 1, INSTR(cf.tag, '.')-1) || '_' || ti.ric || '_' || DECODE(cf.side_id,1,'xx',2,'xx',5,'xx','')
              WHEN INSTR(cf.clientorder_id, '#') > 0 THEN SUBSTR(cf.clientorder_id, 1, INSTR(cf.clientorder_id, '#')-1)
              ELSE cf.clientorder_id
            END
  || ',' || co.tag
  || ',' || t.description
  || ',' || CASE
              WHEN cf.id = xxx THEN 'xxxx'
              ELSE (SELECT t.name FROM taccount t WHERE t.account_id = cf.account_id)
            END as Account
FROM clientf cf, tins ti, thistory co, tdk d, tra t
WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
AND cf.orderhistory_id = co.orderhistory_id
AND cf.reporttype_id = 1
AND ti.inst_id = cf.inst_id
AND (ti.rc LIKE '%.xx' or ti.rc LIKE '%.xx' or ti.rc LIKE '%.xx' )
AND d.de_id = t.de_id
AND t.tr_id = co.tr_id
AND nvl(co.type_id,0) <> 3
AND cf.trid not in (SELECT v2.pid FROM port v2 WHERE v2.sessiondate = cf.sessiondate AND v2.exec_id = 4)
ORDER BY co.cid, time, cf.quantity;

1 Ответ

0 голосов
/ 02 июня 2018

Сначала я бы поговорил с людьми, которым нужен вывод этого запроса, и спросил бы их об отчете и каждом отдельном столбце.Иногда некоторые столбцы больше не нужны, иногда весь отчет.Время выполнения более 8 часов - хорошая точка торга; -)

Далее я бы поставил исходный запрос в одну сторону и начал бы строить тестовый запрос с нуля, по крупицам, например, начиная с clientf, принимая всеэто столбцы в предложении WHERE:

SELECT *
  FROM clientf SAMPLE (0.1) cf 
 WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
   AND cf.reporttype_id = 1;

Если все в порядке, я бы увеличил размер выборки до 99%.Если время выполнения уже слишком велико, вы можете предложить индекс для clientf.sessiondate (или для clientf.reporttype_id, но это вряд ли полезно, так как похоже, что у вас слишком мало разных значений).

После этогоГотово, я бы присоединился к первой таблице:

SELECT *
  FROM clientf SAMPLE (0.1) cf 
 WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
   AND cf.reporttype_id = 1
   AND cf.trid NOT IN (SELECT v2.pid 
                         FROM port v2 
                        WHERE v2.sessiondate = cf.sessiondate 
                          AND v2.exec_id = 4);

Я бы сравнил NOT IN и WHERE NOT EXISTS, не ожидая больших различий.

Затем я присоединился бы к следующейtable (предпочитая лично синтаксис ANSI), снова начиная с небольшого примера, снова добавляя его столбцы к предложению where:

SELECT *
  FROM clientf SAMPLE (0.1) cf 
  FROM thistory co 
    ON cf.orderhistory_id = co.orderhistory_id
 WHERE cf.sessiondate = TO_DATE('xxxxxx','YYYYMMDD')
   AND cf.reporttype_id = 1
   AND nvl(co.type_id,0) <> 3
   AND cf.trid NOT IN (SELECT v2.pid 
                         FROM port v2 
                        WHERE v2.sessiondate = cf.sessiondate 
                          AND v2.exec_id = 4);

Я бы поигрался с заменой nvl(co.type_id,0)<>3 на (co.type_id <>3 OR co.type_id IS NULL), внимательно следя за тем, чтобырезультат логически одинаков.

И так далее ...

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