Oracle pl sql 10g - переместить набор строк из таблицы в таблицу истории с такой же структурой - PullRequest
0 голосов
/ 19 августа 2011

PL SQL перемещает более старые версии данных из таблицы транзакций в таблицу истории с той же структурой и архивом за определенный период -

for each record
insert into tab_hist (select older_versions of current row);
delete from tab (select older_versions of current row);
END

пс: ранее мы не архивировали (без вставки) - нопосле добавления вставки он удвоил время выполнения - так можем ли мы выполнить вставку и удаление одним оператором выбора?поскольку есть большие данные для обработки и для нескольких таблиц

Ответы [ 4 ]

2 голосов
/ 20 августа 2011

Это пакетная операция, верно? В этом случае вам следует избегать Row By Row и использовать обработку множеств. SQL это все о радости множеств.

Oracle обладает фантастическими возможностями массовой обработки SQL. Псевдокод, который вы вставили, выглядел бы примерно так:

declare
    cursor c_oldrecs is
        select * from your_table
        where criterion between some_date and some_other_date;
    type rec_nt is table of your_table%rowtype;
    oldrecs_coll rec_nt;    
begin
     open c_oldrecs;
     loop
         fetch c_oldrecs into oldrecs_coll limit 1000;
         exit when oldrecs_coll.count() = 0;

         forall i in oldrecs_coll.first() oldrecs_coll.last()
             insert into your_table_hist
             values oldrecs_coll(i);
         forall i in oldrecs_coll.first() oldrecs_coll.last()
             delete from your_table
             where pk_col = oldrecs_coll(i).pk_col;
     end loop;
end;
/   

Эта массовая обработка выполняется быстрее, поскольку она отправляет в базу данных тысячу операторов за раз вместо того, чтобы переключаться между PL / SQL и SQL тысячу раз. Предложение LIMIT 1000 предназначено для того, чтобы предотвратить огромный выбор PGA. Эта гарантия может не понадобиться в вашем случае, или вы можете работать с более высокой ценностью.


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

0 голосов
/ 20 августа 2011

Возможно, что медлительность, которую вы видите, обусловлена ​​логикой, которая выбирает, какие строки следует перемещать.Если это так, вы можете получить лучшие результаты, выполнив команду select один раз, чтобы получить значения rowid во вложенной таблице в памяти, а затем выполнить вставку и удаление на основе этого списка;или, альтернативно, управление вашим циклом с помощью запроса, который выбирает строки для перемещения.

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

0 голосов
/ 20 августа 2011

Если вы работаете в редакции Enterprise с опцией разделения, посмотрите обмен разделами.

0 голосов
/ 19 августа 2011

Так просто, как это

CREATE BACKUP_TAB AS SELECT * FROM TAB

Если вы удаляете много строк, вы попадете в табличное пространство отмены, а удаление, которое удаляет, скажем, 100 тыс. Строк, может вызвать проблемы с производительностью.Вы лучше удаляете пакетно, скажем, по 5 тыс. Строк одновременно и фиксируете.

BEGIN
-- Where condition on insert and delete must be the same
loop
  INSERT INTO BACKUP_TAB SELECT * FROM TAB WHERE 1=1 and rownum < 5000; --Your condition here
  exit when SQL%rowcount < 4999;
  commit;
end loop;
loop
  DELETE FROM TAB
   where 1=1--Your condition here
     and rownum < 5000;
  exit when SQL%rowcount < 4999;
  commit;
end loop;
commit;
END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...