2011-12-30 4 views
2

У меня есть процедура поиска первых, последних, максимальных и минимальных цен для серии транзакций в очень большой таблице, которая организована по дате, имени объекта и коду. Мне также нужна сумма транзакций. В таблице около 3 миллиардов строк, и для выполнения этой процедуры требуется много дней. Я хотел бы сократить это время как можно больше. У меня есть индекс на отдельных полях в таблице trans, и, глядя на план объяснения на выбранную часть запросов, используется индекс. Я открыт для предложений по альтернативному подходу. Я использую Oracle 11g R2. Спасибо.Оптимизация Oracle 11g Процедура

declare 
    cursor c_iter is select distinct dt, obj, cd from trans; 
    r_iter c_iter%ROWTYPE; 
    v_fir number(15,8); 
    v_las number(15,8); 
    v_max number(15,8); 
    v_min number(15,8); 
    v_tot number; 
    begin 
    open c_iter; 
    loop 
     fetch c_iter into r_iter; 
     exit when c_iter%NOTFOUND; 

     select max(fir), max(las) into v_fir, v_las 
     from 
      (select 
       first_value(prc) over (order by seq) as "FIR", 
       first_value(prc) over (order by seq desc) as "LAS" 
       from trans 
       where dt = r_iter.DT and obj = r_iter.OBJ and cd = r_iter.CD); 

      select max(prc), min(prc), sum(qty) into v_max, v_min, v_tot 
      from trans 
      where dt = r_iter.DT and obj = r_iter.OBJ and cd = r_iter.CD; 

      insert into stats (obj, dt, cd, fir, las, max, min, tot) 
      values (r_iter.OBJ, r_iter.DT, r_iter.CD, v_fir, v_las, v_max, v_min, v_tot); 

      commit; 
    end loop; 
    close c_iter; 
end; 

ответ

7
alter session enable parallel dml; 

insert /*+ append parallel(stats)*/ 
into stats(obj, dt, cd, fir, las, max, min, tot) 
select /*+ parallel(trans) */ obj, dt, cd 
    ,max(prc) keep (dense_rank first order by seq) fir 
    ,max(prc) keep (dense_rank first order by seq desc) las 
    ,max(prc) max, min(prc) min, sum(qty) tot 
from trans 
group by obj, dt, cd; 

commit; 
  • Один оператор SQL, как правило, значительно быстрее, чем нескольких операторов SQL. Иногда им требуется больше ресурсов, например, более временное табличное пространство, но ваш отдельный курсор, вероятно, уже сортирует всю таблицу на диске.
  • Возможно, вы также захотите включить параллельный DML и параллельный запрос, хотя в зависимости от вашего объекта и настроек системы это может уже произойти. (И это может быть не очень хорошо, в зависимости от ваших ресурсов, но обычно это помогает в больших запросах.)
  • Параллельная запись и APPEND должны повысить производительность, если SQL пишет много данных, но это также означает, что новый таблица не будет восстановлена ​​до следующей резервной копии. (Parallel DML будет автоматически использовать записи прямого пути, но я обычно включаю APPEND в любом случае только в том случае, параллелизм не работает правильно.)

Там очень много, чтобы рассмотреть, даже для такого небольшого запроса, но это где я начну.

+0

спасибо, что это очень изящное решение. я запустим процедуру против текущего скрипта и отчитаюсь. –

+0

этот sql пробежал через 3 часа по сравнению с 3 днями. я совершенно удивлен. Большое вам спасибо за помощь. вы консультируетесь? –

+0

Обратите внимание, что параллельный запрос лицензируется только в Enterprise Edition. Это также не серебряная пуля. – APC

2

Не твердый ответ, который я хотел бы дать, но несколько вещей, чтобы рассмотреть следующие вопросы:

Первым будет с помощью bulk collect. Однако, поскольку вы используете 11g, мы надеемся, что это уже делается для вас автоматически.

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

И наконец, +1 для ответа jonearles. (Я не был уверен, смогу ли я написать все в один SQL-запрос, но я тоже хотел бы предложить это.)

+1

Может рассчитывать на что-то вроде 2k и фиксировать после каждого интервала. – Alfabravo

+1

Это, вероятно, не очень хорошая идея. Согласие с открытым курсором почти наверняка приведет к ошибкам ORA-1555. Кроме того, в этом случае без обработки между выбором и вставкой, вставка в ... выбрать из ...., описанную @jonearles, является явным победителем. –

0

Вы можете попробовать и запустить запрос параллельно, есть разумной Oracle White Paper на этом here. Это не особенность Oracle, которую мне когда-либо приходилось использовать, поэтому у меня нет первоклассного опыта ее прохождения. Вам также потребуется иметь достаточно ресурсов на сервере Oracle, чтобы вы могли запускать параллельные процессы, которые это создаст.

Смежные вопросы