Как улучшить производительность этих операторов вставки для огромного объема данных? - PullRequest
1 голос
/ 15 июня 2019

У меня есть требование вставить огромные (50 ГБ случайных данных) в мою базу данных, чтобы я мог использовать приложение резервного копирования для проверки степени дедупликации.Я написал небольшую процедуру, как показано ниже:

Это занимает более 1 часа.Я не знаю, как улучшить производительность, чтобы получить хорошую пропускную способность для операторов вставки.Я установил SGA как 16 ГБ.

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

alter session force parallel query parallel 4;
create table table_1(
col1 varchar2(400),
-- 50 columns like this
col50 varchar2(400));

create table table_2(
col1 varchar2(400),
-- 50 columns like this
col50 varchar2(400));

create table table_3(
col1 varchar2(400),
-- 50 columns like this
col50 varchar2(400));

create table table_4(
col1 varchar2(400),
-- 50 columns like this
col50 varchar2(400));

Мой скрипт вставки:

Declare
    rows_inserted number := 0;
Begin
  Loop
        Begin
            INSERT INTO table_1(COL1, ..COL50)
            VALUES(dbms_random.string('L', 400),..for all 50 values);
        INSERT INTO table_2(COL1, ..COL50)
            VALUES(dbms_random.string('L', 400),..for all 50 values);
            INSERT INTO table_3(COL1, ..COL50)
            VALUES(dbms_random.string('L', 400),..for all 50 values);
            INSERT INTO table_4(COL1, ..COL50)
            VALUES(dbms_random.string('L', 400),..for all 50 values);
            --Only increment counter when no duplicate exception
            rows_inserted := rows_inserted + 1;
        --Exception When DUP_VAL_ON_INDEX Then Null;
        End;
        exit when rows_inserted = 10000;
    End loop;
    commit;
End;
/

Я пробовал эту процедуру на Oracle12c, который установлен на виртуальной машине rhel 7.Vm имеет 32 ГБ памяти и 20 ГБ подкачки памяти и 16 vcpus.

Это занимает более 1 часа и все еще работает.Как реализовать параллелизм и оптимизировать описанную выше процедуру, чтобы получить хорошую пропускную способность?

1 Ответ

2 голосов
/ 15 июня 2019

Вы делаете вставки в одну строку внутри цикла: это очень медленный способ выполнения вещей. SQL - это язык на основе множеств, а операции над множествами - наиболее эффективный способ выполнения массовых операций. Кроме того, вы также полагаетесь на случайные данные для предоставления дубликатов. Управляйте этим и гарантируйте отношения. Кроме того, как вы можете получить DUP_VAL_ON_INDEX, когда у ваших таблиц нет уникальных ключей? (И если они это сделают, вы не сможете вставить дубликаты, которые вы хотите для своего эксперимента.)

Лучше всего было бы использовать sql:

INSERT INTO table_1(COL1, COL50)
select dbms_random.string('L', 400), dbms_random.string('L', 400)
from dual
connect by level <= 10000
/

INSERT INTO table_1(COL1, COL50)
select *
from table_1
where rownum <= 1000 
/

Это даст вам 11000 строк в table_1, 1000 из которых являются дубликатами. Повторите вторую вставку, чтобы увеличить количество дубликатов.

Не должно быть необходимости в параллелизме.

ALI я хочу сейчас иметь хорошую пропускную способность, которая может вставить 50 ГБ данных в течение 30 минут, с параллелизмом или без него.

Однако эта новая информация меняет мою оценку. Самый простой способ выполнить это параллельно - это создать отдельные подпрограммы для каждой таблицы и запускать каждую в отдельном сеансе.

...