Оптимизация окон Oracle SQL / Возможное решение Oracle PL / SQL? - PullRequest
0 голосов
/ 09 июня 2018

Не могу сказать, насколько полезным было это сообщество!Моя обычная проблема снова мучила меня.У меня есть функциональный код, который отлично работает, скажем, за 1 неделю данных, но не имеет реалистичного времени выполнения, скажем, ... с начала года.(Таблица с событиями составляет 3,5 миллиарда строк, более 10 лет). Я использую оконную функцию, чтобы определить, что произошло с системными событиями.Я также использую оператор case и 2 разных поля для создания пользовательского ключа для группировки событий (хотелось бы, чтобы в исходных данных уже был ключ).

Я плохо знаю PL / SQL, ноЯ думал, кто-то, чтобы показать мне, возможно, как использовать цикл и курсор для циклического перехода через меньшие окна даты?События всегда происходят + - 24 часа .. Тогда я мог бы потянуть, скажем, данные за 3 месяца, но окно смотрело только в пределах + - 24 часа?Я не уверен, возможно, есть ли способ сделать это без PL / SQL.

РЕДАКТИРОВАТЬ: сейчас я думаю, может быть, я мог бы запросить e2.dt, а затем каким-то образом сделать соединение или подзапрос, чтобызапустить логику для временного интервала + -24 часа?До сих пор не совсем понятно, как все это собрать.

Любая помощь очень ценится!

select
  ce.DT
  ,ce.SYSTEM_NO,  ce.EVENT_ID, ce.CALL_START, ce.CALL_CLEAR

  ,case when ce.event_RESTORED  between ce.call_start and 
  ce.call_clear+0.0034722222222222 then ce.event_RESTORED end event_RESTORED
  ,case when ce.call_GOODCALL  between ce.call_start and 
  ce.call_clear+0.0034722222222222 then ce.call_GOODCALL end call_GOODCALL
  ,case when ce.call_clear is not null and (ce.event_RESTORED not between 
  ce.call_start and ce.call_clear+0.0034722222222222 or ce.event_RESTORED is 
  null) and ce.call_GOODCALL between ce.call_start and 
  ce.call_clear+0.0034722222222222 then 'Y' ELSE 'N' end  call_CONNECTED

 from

 (SELECT system_no,
     dt as dt,
     e2.event_id,
       min(
     case when   e2.event_id in ('XXX001') 
       THEN e2.dt
       END
     ) OVER (
      partition by e2.system_no, case when e2.event_no is not null then to_char(e2.event_no) when  INSTR(e2.commnt, 'callid:') <> 0 then SUBSTR(e2.commnt, INSTR(e2.commnt, 'callid:') + 7) else to_char(e2.callid) end
     ) AS call_start,
    min(
     case when   e2.event_id in ('XXXCC') 
       THEN e2.dt
       END
     ) OVER (
      partition by   e2.system_no, case when e2.event_no is not null then to_char(e2.event_no) when  INSTR(e2.commnt, 'callid:') <> 0 then SUBSTR(e2.commnt, INSTR(e2.commnt, 'callid:') + 7) else to_char(e2.callid) end
     ) AS call_clear
     , min(
     case when   e2.event_id in ('XXXRE') 
       THEN e2.dt
       END
     ) OVER (
       partition by e2.system_no
      order by e2.DT
     RANGE BETWEEN 0 FOLLOWING AND 1 FOLLOWING 
     ) AS event_restored
         , min(
     case when    e2.event_id in ('XXX003','XXX004') 
       THEN e2.dt
       END
     ) OVER (
       partition by e2.system_no
      order by e2.DT
     RANGE BETWEEN 0 FOLLOWING AND 1 FOLLOWING 
     ) AS call_goodcall
     from CALLEVENTS e2
where 
  e2.dt >= '1-MAR-2018') ce
--e2.dt >= '1-JUN-2018') ce

where  call_clear is not null;

Ответы [ 2 ]

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

Я бы начал добавлять индекс:

create index ix1 on CALLEVENTS (dt, system_no, event_no,
  commnt, callid, event_id);

Этот индекс будет производить сканирование диапазона индекса .Надеемся, что он даже может произвести сканирование Index Only , что еще быстрее.

Пожалуйста, попробуйте и дайте мне знать, как это работает.Если это все еще медленно, пожалуйста, опубликуйте план выполнения этого запроса.

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

Я закончил тем, что создал таблицу в своей личной схеме и добавил индексы для dt, system_no и event_no ... Я также сделал внутреннее соединение в той же таблице с условием e3.dt2 между e.dt-1 иe.dt + 1 .. этот запрос теперь выполняется примерно за 1 час .. for> = 1-MAR-2018 .. но если у кого-то есть какие-либо улучшения, которые могли бы ускорить это, это было бы замечательно!или просто хороший совет по коду / формату .. потому что я знаю ... мой очень ... небрежный.

select
ce.DT
,ce.SYSTEM_NO,  ce.EVENT_ID, ce.CALL_START, ce.CALL_CLEAR

,case when ce.event_RESTORED  between ce.call_start and 
ce.call_clear+0.0034722222222222 then ce.event_RESTORED end event_RESTORED
,case when ce.call_GOODCALL  between ce.call_start and 
ce.call_clear+0.0034722222222222 then ce.call_GOODCALL end call_GOODCALL
,case when ce.call_clear is not null and (ce.event_RESTORED not between 
ce.call_start and ce.call_clear+0.0034722222222222 or ce.event_RESTORED is 
null) and ce.call_GOODCALL between ce.call_start and 
ce.call_clear+0.0034722222222222 then 'Y' ELSE 'N' end  call_CONNECTED


from

(SELECT system_no,
     dt as dt,
     e.event_id,
     e3.*



  from CALLEVENTS e

  inner join (select
  system_no,
 dt as dt,
 e2.event_id,
   min(
 case when   e2.event_id in ('XXX001') 
   THEN e2.dt
   END
 ) OVER (
  partition by e2.system_no, case when e2.event_no is not null then to_char(e2.event_no) when  INSTR(e2.commnt, 'callid:') <> 0 then SUBSTR(e2.commnt, INSTR(e2.commnt, 'callid:') + 7) else to_char(e2.callid) end
 ) AS call_start,
min(
 case when   e2.event_id in ('XXXCC') 
   THEN e2.dt
   END
 ) OVER (
  partition by   e2.system_no, case when e2.event_no is not null then to_char(e2.event_no) when  INSTR(e2.commnt, 'callid:') <> 0 then SUBSTR(e2.commnt, INSTR(e2.commnt, 'callid:') + 7) else to_char(e2.callid) end
 ) AS call_clear
 , min(
 case when   e2.event_id in ('XXXRE') 
   THEN e2.dt
   END
 ) OVER (
   partition by e2.system_no
  order by e2.DT
 RANGE BETWEEN 0 FOLLOWING AND 1 FOLLOWING 
 ) AS event_restored
     , min(
 case when    e2.event_id in ('XXX003','XXX004') 
   THEN e2.dt
   END
 ) OVER (
   partition by e2.system_no
  order by e2.DT
 RANGE BETWEEN 0 FOLLOWING AND 1 FOLLOWING 
 ) AS call_goodcall



     from CALLEVENTS e2


 ) e3 on e3.sys = e.system_no and e3.seq = e.event_no and e3.dt2 between 
 e.dt-1 and e.dt+1

 where 

 e.dt >= '1-MAR-2018') se




 where  call_clear is not null 
...