프린트 하기

OS 환경 : Oracle Linux 7.6 (64bit)

 

DB 환경 : Oracle Database 19.3.0.0

 

방법 : 오라클 19c 일반 insert, insert all, union all insert 성능 테스트

컬럼 1개인 테이블에 대해 일반 insert, insert all, union all insert, bulk insert 방식을 사용해서 데이터 5000건을 insert 할때

어떤 방식으로 insert 하는게 빠른지 테스트해봄(기존에는 100만건으로 하려했지만 너무 느려서 갯수를 줄임)

 

 

구문 설명
일반 insert 구문 : 일반 insert는 가장 기본적인 형태로, 하나의 행을 삽입하거나 itas(insert into table select~)여러 행을 한번에 삽입할 수 있음
사용 예시 :

1
2
insert into table_name (column1, column2, column3) 
values (value1, value2, value3);

 

 

insert all 구문 : 하나의 트랜잭션으로 여러 행을 동시에 삽입할 수 있는 구문으로, 여러 테이블에 걸쳐 삽입도 가능함
사용 예시 :

1
2
3
4
5
insert all
  into table1 (column1, column2) values (value1, value2)
  into table2 (column1, column2) values (value3, value4)
  into table3 (column1, column2) values (value5, value6)
select * from dual;

 

 

union all insert 구문 : 여러 개의 select 문을 사용하여 한번에 여러 행을 삽입함(위에서 설명한 itas방식)
사용 예시 :

1
2
3
4
5
6
insert into intest5 (col1)
select 1 from dual union all
select 2 from dual union all
select 3 from dual union all
...
select 5000 from dual;

 

 

Bulk insert 구문 : 테이블 레코드 형식의 배열에 값을 저장하고 한번에 insert 구문을 실행함
사용 예시 : 대량 데이터 삽입 insert 빠르게 실행 벌크 insert ( https://positivemh.tistory.com/183 )

 

 

테스트
1. 일반 insert 테스트(일반 sql)
2. 일반 insert 테스트(pl/sql)
3. insert all 테스트(일반 sql)
4. insert all 테스트(pl/sql)
5. union all insert 테스트(일반 sql)
6. union all insert 테스트(pl/sql)
7. bulk insert 테스트
(다른 테스트는 5천건으로 테스트했지만 bulk는 빨라서 100배인 50만건을 insert 함)

 

 

테스트
샘플 테이블 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SQL> 
drop table intest1 purge;
drop table intest2 purge;
drop table intest3 purge;
drop table intest4 purge;
drop table intest5 purge;
drop table intest6 purge;
drop table intest7 purge;
create table intest1 (col1 number);
create table intest2 (col1 number);
create table intest3 (col1 number);
create table intest4 (col1 number);
create table intest5 (col1 number);
create table intest6 (col1 number);
create table intest7 (col1 number);
 
Table created.

 

 

1. 일반 insert 테스트(일반 sql)
insert 쿼리 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SQL> 
spool in1.sql
set lines 200 pages 10000
select 'insert into intest1 (col1) values ('||level||');' insql 
from dual 
connect by level <= 5000;
 
INSQL
----------------------------------------------------------------------------
insert into intest1 (col1) values (1);
..
insert into intest1 (col1) values (5000);
 
5000 rows selected.

 

 

vi로 SQL 이외 문자 삭제 및 마지막에 commit; 추가

 

 

10046 트레이스 실행

1
2
3
SQL> 
alter session set tracefile_identifier='INTEST1';
alter session set events '10046 trace name context forever, level 12';

 

 

insert 실행

1
SQL> @in1.sql

 

 

10046 트레이스 해제

1
2
3
SQL> alter session set events '10046 trace name context off';
 
Session altered.

 

 

트레이스 경로 확인

1
2
3
4
5
6
7
8
9
SQL> 
set lines 200 pages 1000
col value for a100
select value from v$diag_info
where name = 'Default Trace File';
 
VALUE
----------------------------------------------------------------------------------------------------
/ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/oracle19_ora_14903_INTEST1.trc

 

 

tkprof 로 변환

1
2
$ cd /ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/
$ tkprof oracle19_ora_14903_INTEST1.trc oracle19_ora_14903_INTEST1.txt sys=no

 

 

trace 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ vi oracle19_ora_14903_INTEST1.txt
********************************************************************************
 
OVERALL TOTALS FOR ALL NON-RECURSIVE STATEMENTS
 
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse     5002      1.20       1.67          0          0          0           0
Execute   5002      0.12       0.18          0         63      10207        5000
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total    10004      1.32       1.86          0         63      10207        5000
 
Misses in library cache during parse: 5000
Misses in library cache during execute: 1

1.86초 소요됨

 

 

2. 일반 insert 테스트(pl/sql)
세션 재접속 후 10046 트레이스 실행

1
2
3
SQL> 
alter session set tracefile_identifier='INTEST2';
alter session set events '10046 trace name context forever, level 12';

 

 

insert 실행

1
2
3
4
5
6
7
8
9
SQL>
begin
    for i in 1..5000 loop
        insert into intest2 (col1) values (i);
    end loop;
end;
/
 
PL/SQL procedure successfully completed.

 

 

10046 트레이스 해제

1
2
3
SQL> alter session set events '10046 trace name context off';
 
Session altered.

 

 

트레이스 경로 확인

1
2
3
4
5
6
7
8
9
SQL> 
set lines 200 pages 1000
col value for a100
select value from v$diag_info
where name = 'Default Trace File';
 
VALUE
----------------------------------------------------------------------------------------------------
/ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/oracle19_ora_17428_INTEST2.trc

 

 

tkprof 로 변환

1
2
$ cd /ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/
$ tkprof oracle19_ora_17428_INTEST2.trc oracle19_ora_17428_INTEST2.txt sys=no

 

 

trace 확인

1
2
3
4
5
6
7
8
9
10
11
$ vi oracle19_ora_17428_INTEST2.txt
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute   5000      0.12       0.25          0         63       5224        5000
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total     5001      0.12       0.25          0         63       5224        5000
 
Misses in library cache during parse: 1
Misses in library cache during execute: 1

0.25초 소요됨

 

 

3. insert all 테스트(일반 sql)
세션 재접속 후 진행
insert 쿼리 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SQL> 
spool in3.sql
set lines 200 pages 10000
select 'insert all' from dual 
union all
select 'into intest3 (col1) values ('||level||')' insql 
from dual 
connect by level <= 5000
union all
select 'select * from dual;' from dual;
 
INSERTALL
----------------------------------------------------------------------------
insert all
into intest3 (col1) values (1)
..
into intest3 (col1) values (5000)
select * from dual;
 
5002 rows selected.

 

 

vi로 SQL 이외 문자 삭제 및 마지막에 commit; 추가

 

 

10046 트레이스 실행

1
2
3
SQL> 
alter session set tracefile_identifier='INTEST3';
alter session set events '10046 trace name context forever, level 12';

 

 

insert 실행

1
SQL> @in3.sql

 

 

10046 트레이스 해제

1
2
3
SQL> alter session set events '10046 trace name context off';
 
Session altered.

 

 

트레이스 경로 확인

1
2
3
4
5
6
7
8
9
SQL> 
set lines 200 pages 1000
col value for a100
select value from v$diag_info
where name = 'Default Trace File';
 
VALUE
----------------------------------------------------------------------------------------------------
/ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/oracle19_ora_25569_INTEST3.trc

 

 

tkprof 로 변환

1
2
$ cd /ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/
$ tkprof oracle19_ora_25569_INTEST3.trc oracle19_ora_25569_INTEST3.txt sys=no

 

 

trace 확인

1
2
3
4
5
6
7
8
9
10
11
$ vi oracle19_ora_25569_INTEST3.txt
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      3.69       7.43          2      10022          0           0
Execute      1      3.25       7.65        128        633      11123        5000
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      6.94      15.09        130      10655      11123        5000
 
Misses in library cache during parse: 1
Misses in library cache during execute: 1

15.09초 소요됨

 

 

4. insert all 테스트(pl/sql)
세션 재접속 후 10046 트레이스 실행

1
2
3
SQL> 
alter session set tracefile_identifier='INTEST4';
alter session set events '10046 trace name context forever, level 12';

 

 

insert 실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
SQL>
declare
    v_sql clob := empty_clob();
    v_chunk varchar2(32767);
begin
    dbms_lob.createtemporary(v_sql, true);
 
    v_chunk := 'insert all ';
    dbms_lob.writeappend(v_sql, length(v_chunk), v_chunk);
 
    for i in 1..5000 loop
        v_chunk := 'into intest4 (col1) values (' || i || ') ';
        dbms_lob.writeappend(v_sql, length(v_chunk), v_chunk);
    end loop;
 
    v_chunk := 'select * from dual';
    dbms_lob.writeappend(v_sql, length(v_chunk), v_chunk);
 
    execute immediate v_sql;
 
    dbms_lob.freetemporary(v_sql);
end;
/
 
PL/SQL procedure successfully completed.

 

 

10046 트레이스 해제

1
2
3
SQL> alter session set events '10046 trace name context off';
 
Session altered.

 

 

트레이스 경로 확인

1
2
3
4
5
6
7
8
9
SQL> 
set lines 200 pages 1000
col value for a100
select value from v$diag_info
where name = 'Default Trace File';
 
VALUE
----------------------------------------------------------------------------------------------------
/ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/oracle19_ora_39127_INTEST4.trc

 

 

tkprof 로 변환

1
2
$ cd /ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/
$ tkprof oracle19_ora_39127_INTEST4.trc oracle19_ora_39127_INTEST4.txt sys=no

 

 

trace 확인

1
2
3
4
5
6
7
8
9
10
11
$ vi oracle19_ora_39127_INTEST4.txt
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      3.91       7.86          0          0          0           0
Execute      1      3.67       7.40          0         63      10212        5000
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      7.59      15.27          0         63      10212        5000
 
Misses in library cache during parse: 1
Misses in library cache during execute: 1

15.27초 소요됨
이 plsql 트레이스의 SQL을 보면 3번과 동일한 방식으로 수행되어 속도차이가 없는걸로 보임

 

 

5. union all insert 테스트(일반 sql)
세션 재접속 후 진행
insert 쿼리 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SQL> 
spool in5.sql
set lines 200 pages 10000
select 'insert into intest5 (col1)' insql from dual 
union all
select 'select '||level||' from dual union all' 
from dual 
connect by level <= 5000
union all
select ';' from dual;
 
INSQL
-------------------------------------------------------------------
insert into intest5 (col1)
select 1 from dual union all
..
select 5000 from dual union all
;
 
5002 rows selected.

 

 

vi로 SQL 이외 문자 삭제 및 마지막에 commit; 추가

 

 

10046 트레이스 실행

1
2
3
SQL> 
alter session set tracefile_identifier='INTEST5';
alter session set events '10046 trace name context forever, level 12';

 

 

insert 실행

1
SQL> @in5.sql

 

 

10046 트레이스 해제

1
2
3
SQL> alter session set events '10046 trace name context off';
 
Session altered.

 

 

트레이스 경로 확인

1
2
3
4
5
6
7
8
9
SQL> 
set lines 200 pages 1000
col value for a100
select value from v$diag_info
where name = 'Default Trace File';
 
VALUE
----------------------------------------------------------------------------------------------------
/ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/oracle19_ora_40828_INTEST5.trc

 

 

tkprof 로 변환

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ cd /ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/
$ tkprof oracle19_ora_40828_INTEST5.trc oracle19_ora_40828_INTEST5.txt sys=no
 
trace 확인
$ vi oracle19_ora_40828_INTEST5.txt
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      5.57      11.22          0         10          0           0
Execute      1      5.48      11.07          0         51        156        5000
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2     11.06      22.29          0         61        156        5000
 
Misses in library cache during parse: 1
Misses in library cache during execute: 1

22.29초 소요됨

 

 

6. union all insert 테스트(pl/sql)
세션 재접속 후 10046 트레이스 실행

1
2
3
SQL> 
alter session set tracefile_identifier='INTEST6';
alter session set events '10046 trace name context forever, level 12';

 

 

insert 실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SQL>
declare
    v_sql clob := empty_clob();
    v_chunk varchar2(32767);
begin
    dbms_lob.createtemporary(v_sql, true);
 
    v_chunk := 'insert into intest6 (col1) ';
    dbms_lob.writeappend(v_sql, length(v_chunk), v_chunk);
 
    for i in 1..5000 loop
        if i = 5000 then
            v_chunk := 'select ' || i || ' from dual';
        else
            v_chunk := 'select ' || i || ' from dual union all ';
        end if;
        dbms_lob.writeappend(v_sql, length(v_chunk), v_chunk);
    end loop;
 
    execute immediate v_sql;
 
    dbms_lob.freetemporary(v_sql);
end;
/
 
PL/SQL procedure successfully completed.

 

 

10046 트레이스 해제

1
2
3
SQL> alter session set events '10046 trace name context off';
 
Session altered.

 

 

트레이스 경로 확인

1
2
3
4
5
6
7
8
9
SQL> 
set lines 200 pages 1000
col value for a100
select value from v$diag_info
where name = 'Default Trace File';
 
VALUE
----------------------------------------------------------------------------------------------------
/ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/oracle19_ora_48893_INTEST6.trc

 

 

tkprof 로 변환

1
2
$ cd /ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/
$ tkprof oracle19_ora_48893_INTEST6.trc oracle19_ora_48893_INTEST6.txt sys=no

 

 

trace 확인

1
2
3
4
5
6
7
8
9
10
11
$ vi oracle19_ora_48893_INTEST6.txt
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      5.64      11.43          0          0          0           0
Execute      1      5.59      11.28          0         61        155        5000
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2     11.24      22.72          0         61        155        5000
 
Misses in library cache during parse: 1
Misses in library cache during execute: 1

22.72초 소요됨
이 plsql 트레이스의 SQL을 보면 5번과 동일한 방식으로 수행되어 속도차이가 없는걸로 보임

 

 

7. bulk insert 테스트

(다른 테스트는 5천건으로 테스트했지만 bulk는 빨라서 100배인 50만건을 insert 함)
세션 재접속 후 10046 트레이스 실행

1
2
3
SQL> 
alter session set tracefile_identifier='INTEST7';
alter session set events '10046 trace name context forever, level 12';

 

 

insert 실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SQL>
declare
 
type tbl_ins is table of intest7%rowtype index by binary_integer;
w_ins tbl_ins;
begin
 
for i in 1..500000 loop 
   w_ins(i).col1 :=i;
end loop;
 
forall i in 1..500000 insert into intest7 values w_ins(i);
commit;
end;
/
 
PL/SQL procedure successfully completed.

 

 

10046 트레이스 해제

1
2
3
SQL> alter session set events '10046 trace name context off';
 
Session altered.

 

 

트레이스 경로 확인

1
2
3
4
5
6
7
8
9
SQL> 
set lines 200 pages 1000
col value for a100
select value from v$diag_info
where name = 'Default Trace File';
 
VALUE
----------------------------------------------------------------------------------------------------
/ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/oracle19_ora_24879_INTEST7.trc

 

 

tkprof 로 변환

1
2
$ cd /ORA19/app/oracle/diag/rdbms/oracle19/oracle19/trace/
$ tkprof oracle19_ora_24879_INTEST7.trc oracle19_ora_24879_INTEST7.txt sys=no

 

 

trace 확인

1
2
3
4
5
6
7
8
9
10
11
$ vi oracle19_ora_24879_INTEST7.txt
call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.17       0.35          0        986       8841      500000
Fetch        0      0.00       0.00          0          0          0           0
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        2      0.17       0.35          0        986       8841      500000
 
Misses in library cache during parse: 1
Misses in library cache during execute: 1

0.35초 소요됨

 

 

결론 :
1. 일반 insert(일반 sql) : 1.86초(parse call 5000번 수행)
2. 일반 insert(pl/sql) : 0.25초(어플리케이션 커서 캐싱 효과 parse call 1번만 수행)
3. insert all(일반 sql) : 15.09초
4. insert all(pl/sql) : 15.27초
5. union all insert(일반 sql) : 22.29초
6. union all insert(pl/sql) : 22.72초
7. bulk insert : 0.35초(50만건)

 

전체적으로 보면 벌크 insert가 가장 빨랐고,

컬럼 1개인 테이블에 대해 5천건 insert를 기준으로 일반 insert(pl/sql포함)이 가장 빠르고 그다음 insert all이 빨랐고 union all을 이용한 insert 이 가장 느렸음

 

참고로 컬럼 10개인 테이블에 대해 5천건 insert를 기준으로 
일반 insert(pl/sql포함)이 가장 빠르고 그다음 union all을 이용한 insert 이 빨랐고 insert all이 가장 느렸음

참고 : 오라클 19c 일반 insert, insert all, union all insert 성능 테스트2 ( https://positivemh.tistory.com/1109 )

 

 

참조 : 

https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/INSERT.html
https://positivemh.tistory.com/183

https://positivemh.tistory.com/1109