# 데이터베이스/오라클

[ORACLE] 데이터베이스 CALL이 성능에 미치는 영향 테스트

dev-jjong 2023. 7. 26. 09:16
create table source
as
select b.no, a.*
from (select * from emp where rownum <= 10) a,
     (select rownum as no from dual connect by level <= 100000)b;


create table target
as
select * from source where 1=2;

source 테이블에는 100만건의 데이터가 들어있다.

 

1. loop가 종료된 후에 커밋 (수행시간: 15초)

source 테이블의 데이터를 target 테이블로 PL/SQL의 루프를 돌려서 건건이 입력해보자.

begin
  for s in (select * from source)
  loop
	  insert into target values(s.no, s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno);
	  
  end loop;
  commit;
end;
/

/*
==========================[Start Time : 2023/07/26 08:57:05]==========================
실행 완료. Time used: 15116 Millis

*/

 

15초가량 시간이 걸렸다. 루프를 돌면서 건건이 call이 발생했지만, 네트워크를 경유하지 않는 Recursive Call이라서

그나마 15초만에 수행이 된 것이다.

 


2. loop안쪽에서 건건히 commit (수행시간: 48초)

이번에는 아래 PL/SQL문을 실행해보자.

커밋을 루프 안쪽으로 옮겨보았다.

begin
  for s in (select * from source)
  loop
	  insert into target values(s.no, s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno);
	  commit;
  end loop;
  
end;
/

/*
==========================[Start Time : 2023/07/26 08:54:35]==========================
실행 완료. Time used: 48607 Millis
*/

 

15초 걸리던게 48초로 늘어났다. 성능도 문제지만 커밋을 이렇게 자주하게 되면 트랜잭션 원자성에도 문제가 생긴다.


3. loop안쪽에서 적당한 주기로 commit (수행시간: 18초)

declare
i NUMBER :=0;
begin
  for s in (select * from source)
  loop
	  insert into target values(s.no, s.empno, s.ename, s.job, s.mgr, s.hiredate, s.sal, s.comm, s.deptno);
	  i := i+1;
	  if mod(i, 100000) = 0 then --10만 번에 한 번씩 커밋
	  commit;
	  end if;
  end loop;
  
end;
/

/*
==========================[Start Time : 2023/07/26 09:09:32]==========================
실행 완료. Time used: 18633 Millis
*/​

이렇게 처리하면 맨 마지막에 한 번 커밋하는 것과 비교해서 크게 성능차이가 없다.


4. One SQL로 처리하는 방법 (수행시간: 0.8초)

insert into target 
select * from source;

/*
==========================[Start Time : 2023/07/26 09:12:29]==========================
실행 완료. Time used: 796 Millis
*/

단 한 번의 call로 처리하니 0.8초만에 수행이 되었다.

가급적 One SQL로 처리하도록 하자!!