如何为大量数据提取提高此插入语句的性能?

时间:2019-06-15 09:07:06

标签: oracle performance plsql oracle12c bulk-operations

我需要向数据库中插入大量(50GB的随机数据),以便可以使用备份应用程序检查重复数据删除率。我写了一个如下的小程序

这需要1个多小时。我不知道如何提高性能,以便为insert语句获得良好的吞吐量。我已将SGA设置为16GB。

我是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;
/

我已经在安装在rhel 7 VM上的Oracle12c上尝试了此过程。 Vm具有32 GB内存和20GB交换内存以及16个vcpus。

这需要1个多小时,并且仍在运行。如何实现并行性并优化上述过程以获得良好的吞吐率?

1 个答案:

答案 0 :(得分:2)

您正在循环内插入单行:这是一种很慢的处理方式。 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 
/

这将为您在table_1中提供11000行,其中1000行是重复的。重复第二次插入以增加重复项的数量。

应该不需要并行性。

  

我现在想要的是良好的吞吐量,无论有没有并行性,它都可以在30分钟内插入50 GB的数据。

但是,这条新信息改变了我的评估。并行运行此命令的最简单方法是为每个表构建单独的例程,并在单独的会话中运行每个例程。