Таблица обновлений с 500+ миллионами записей с использованием 50 параллельных сеансов SQLPLUS с групповым сбором LIMIT и FORALL - PullRequest
0 голосов
/ 12 марта 2019

Я новичок в Oracle, и я пытался улучшить производительность обновления огромной таблицы (500+ миллионов записей) - независимо от того, сколько я стараюсь, это убивает производительность.

Я пытаюсь обновить таблицу с 500 миллионами записей, используя 50 параллельных сессий SQLPLUS с групповым сбором LIMIT и FORALL - что занимает огромное время (Истекло: 04: 32: 30.29).

  CURSOR NIT_CURSOR IS
  SELECT SA_ROWID, NEW_TRX_1, NEW_TRX_2
  FROM NIT_SA
  WHERE MOD(DBMS_ROWID.rowid_block_number(SA_ROWID),&2) = &1;
Note: &2 is 50 where as &1 is number of instance invoked from shell between (0-49), 
SA_ROWID is acutal rowid from SA Table

Теперь оператор UPDATE выглядит следующим образом:

  C_COMMIT         CONSTANT PLS_INTEGER := 10000;
  FETCH NIT_CURSOR BULK COLLECT INTO BLK_NIT_SA LIMIT C_COMMIT;     

  FORALL indx IN 1 .. BLK_NIT_SA.COUNT
  UPDATE SA
  SET INS_TRX_ID = BLK_NIT_SA(indx).NEW_TRX_1,
      UPD_TRX_ID = BLK_NIT_SA(indx).NEW_TRX_2
  WHERE ROWID = BLK_NIT_SA(indx).SA_ROWID;

Этот скрипт вызывается KSH в 50 параллельных сеансах SQLPLUS:

typeset -A sqlFile
sqlFile[2.3.sql]=50
for counter_i in "${!sqlFile[@]}"
do
  for counter_j in {0..$((${sqlFile[$counter_i]}-1))}
  do
     sqlplus -s ${DATABASE_CONNECT} @${SQLFILE} "${SPOOLFILE}" ${sqlFile[$counter_i]} $counter_j &
  done
done

Насколько я понимаю, так как я непосредственно использую rowid таблицы SA, который был бы самым быстрым способом доступа к строке, и 50 сеанс SQL должен фактически обрабатывать данные намного быстрее, тогда как, как я наблюдал, вскоре я Если увеличить число параллельных процессов сеанса SQL с 50 до 100, мое время обновления каждого процесса увеличивается на 2 часа, то есть с 4,5 часа до 7,5 часа.

Я собираюсь закончить это через 1,5-2 часа. не уверен, что это реалистично.

Может кто-нибудь, пожалуйста, помогите мне с выше?

Ответы [ 2 ]

3 голосов
/ 12 марта 2019

500+ миллионов записей не очень хорошая идея, вы можете указать структуру таблиц и то, какой столбец необходимо обновить. Мы можем рассмотреть следующие варианты:

  1. если требуемые новые значения в таблице могут быть рассчитаны динамически, тогда мы можем создать представление поверх таблицы, чтобы всякий раз, когда мы читаем представление, мы могли получить требуемые значения.

  2. создать новую таблицу и при необходимости вставить все данные из существующей таблицы (с новыми значениями для этих столбцов) и удалить старую таблицу, переименовать новую

2 голосов
/ 12 марта 2019

Преобразование PL / SQL в один оператор SQL и использование параллелизма операторов должно значительно повысить производительность:

alter session enable parallel dml;

merge /*+ parallel(50) */ into sa using
(
    select sa_rowid, new_trx_1, new_trx_2
    from nit_sa
) nit_sa
on (sa.rowid = nit_sa.sa_rowid)
when matched then update set
    sa.ins_trx_id = nit_sa.new_trx_1,
    sa.upd_trx_id = nit_sa.new_trx_2;

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

Параллелизм в теории прост - просто добавьте подсказку, и время выполнения может увеличиться на порядок. Но сделать это правильно на практике может быть сложно. Параллелизм требует Enterprise Edition, достаточных ресурсов, разумной конфигурации и т. Д. А параллельный DML будет блокировать всю таблицу до тех пор, пока оператор не будет выполнен, - никакой другой DML не может одновременно работать с таблицей. (Хотя другие процессы все еще могут читать из таблицы.)

...