프로그래밍/이것저것 일하면서
[데이터베이스/오라클] 대량 insert 속도 개선
김퇴근
2023. 3. 17. 11:04
반응형
요즘 푸시 발송 속도 개선을 하고 있는데, FCM 발송 후 결과 저장이나 잘못된 토큰 삭제 처리에서 병목이 생기는 것을 확인하였다. 그래서 사용자의 푸시 '알림함'에 대량 insert 하는 부분을 개선하고자 오라클 다중 insert 속도를 개선하는 방법을 찾아보았다.
### 기존
INSERT INTO SOME_TABLE (col1, col2 ..)
VALUES (#{val1}, #{val2} ..);
### 1차 수정
하나의 commit으로 처리될 수 있도록 묶었다. (참고로 spring + mybatis 사용하여 처리 중)
로컬 디비로 1000건 insert 테스트 시 26초가 나왔다.
BEGIN
INSERT INTO SOME_TABLE (col1, col2 ..)
VALUES (#{val1}, #{val2} ..);
INSERT INTO SOME_TABLE (col1, col2 ..)
VALUES (#{val1}, #{val2} ..);
INSERT INTO SOME_TABLE (col1, col2 ..)
VALUES (#{val1}, #{val2} ..);
END;
-- commit
### 2차 수정
아래처럼 INSERT INTO ... SELECT FROM DUAL UNION ALL ... 구문으로 수정했습니다.
INSERT INTO SOME_TABLE (col1, col2 ..)
SELECT SOME_SEQUENCE.nextval, #{val2} .. FROM DUAL UNION ALL
SELECT SOME_SEQUENCE.nextval, #{val2} .. FROM DUAL UNION ALL
SELECT SOME_SEQUENCE.nextval, #{val2} .. FROM DUAL;
그런데 시퀀스 사용에 문제가 있네요. 찾아보니 시퀀스의 사용 제약 중 UNION과는 사용할 수 없다는 것이 있었습니다.
### 3차 수정
시퀀스 오류를 회피하기 위해 시퀀스를 반환하는 함수를 생성하였습니다. 실행이 잘 되고, 1000건 insert 실행 속도가 약 1/5로 줄어들었습니다. 해피엔딩입니다.
INSERT INTO SOME_TABLE (col1, col2 ..)
SELECT FN_GET_NEXT_ID(), #{val2} .. FROM DUAL UNION ALL
SELECT FN_GET_NEXT_ID(), #{val2} .. FROM DUAL UNION ALL
SELECT FN_GET_NEXT_ID(), #{val2} .. FROM DUAL;
## 참고: 시퀀스를 반환하는 함수
create or replace
FUNCTION FN_GET_NEXT_SOME_ID RETURN NUMBER AS
num NUMBER;
BEGIN
SELECT MYUSER.SEQ_SOME_ID.nextval
INTO num
FROM dual;
return num;
END FN_GET_NEXT_SOME_ID;
반응형