메모장

블로그 이미지

동팡

https://github.com/ehdvudee

Insert Multiple - Oracle(Tibero) 포팅 삽질기

개발관련/삽질 2019. 9. 11. 14:06

DB 포팅을 진행할 때 insert multiple 부분에 대한 삽질기

 

목차

 - 문제

 - 삽질 과정 - 1: insert multiple with sequence 

 - 삽질 과정 - 2: mybatis malfunction useGeneratedKeys

 - 해결 방안

 - 고찰 1 (insert의 방법)

 - 고찰 2 (prepared statement와 foreach insert)

 

문제

PostgreSQL/MySQL/MariaDB에서 지원되는 쿼리를 Oracle(Tibero) DBMS로 포팅을 진행한다.

문제의 쿼리는 아래와 같다.

<insert id="insertServiceCodeList" parameterType="serviceCodeVo" useGeneratedKeys="true" keyColumn="code" keyProperty="code">
  insert into service_code ( 
      serv_info_seq_id, name, 
      default_key_type, 
      cre_date,
      creator,
      description,
      state 
  ) values 
  	<foreach collection="list" item="item" separator=","> 
  	( 
  		#{item.servInfoSeqId},
        #{item.name},
        #{item.defaultKeyType},
        now(),
        #{item.creator}, 
        #{item.description},
        0 
	)
    </foreach>
</insert>

DDL seq_id의 Default는 sequence.nextval 또는 auto_increment이다.

 

삽질 과정 - 1: insert multiple with sequence 

 - Oracle은 위의 쿼리 지원안함.

 - Oracle은 insert all을 해야함

 - 근데 insert all 할 때 sequence.nextval이 지원안됨 ㅡㅡ(insert into 단일건에 대해서만 지원함)

 - 이것에 대해서는 2가지 해결 방법이 있음.

 - 해결방안 1

   

Create Sequence service_code_seq;
create or replace function get_seq( seq_name in varchar2 ) 
return 
  number 
is
  v_num number;
  sql_stmt varchar2(64);
begin
  sql_stmt := 'select ' || seq_name || '.nextval from dual';
  execute immediate sql_stmt into v_num;
  return v_num;
end;
<insert id="insertServiceCodeList" parameterType="serviceCodeVo" useGeneratedKeys="true" keyColumn="code" keyProperty="code">
insert all
     <foreach collection="list" item="item" >
        into service_code (
            code,
            serv_info_seq_id,
            name,
            default_key_type,
            cre_date,
            creator,
            description,
            state
        ) values (
            get_seq( 'service_code_seq' ),
            #{item.servInfoSeqId},
            #{item.name},
            #{item.defaultKeyType},
            systimestamp,
            #{item.creator},
            #{item.description},
            0
        )
    </foreach>
    select * from dual;
</insert>

- 해결방안 2

<insert id="insertServiceCodeList" parameterType="serviceCodeVo" useGeneratedKeys="true" keyColumn="code" keyProperty="code">
    insert into service_code (
        code,
        serv_info_seq_id,
        name,
        default_key_type,
        cre_date,
        creator,
        description,
        state
    ) select
        service_code_seq.nextval,
        servInfoSeqId,
        name,
        defaultKeyType,
        systimestamp,
        creator,
        description,
        0
    from (
    <foreach collection="list" item="item" separator="union all"> 
        select
            #{item.servInfoSeqId} servInfoSeqId,
            #{item.name} name,
            #{item.defaultKeyType} defaultKeyType,
            #{item.creator} creator,
            #{item.description} description
        from
            dual
    </foreach>
    )
</insert>

삽질 과정 - 1 - 결론과 동시에 문제

 - 위의 해결방안 1,2 insert multiple with sequence 가능함.

 - 해결방안 2는 추천안함( SQL 실행계획을 분석 하면 인라인뷰를 만들고/병합하느냐고 DB cost 잡아먹음 ㅋㅋㅋㅋ)

 - 문제: MyBatis의 useGeneratedKeys가 지원안됨 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

삽질 과정 - 2: mybatis malfunction useGeneratedKeys

 - 일단 안됨 그냥 안됨 

 - Syntax Error 뿜뿜~!!!

 - 내가 원하는 것은 시퀀스ID 값을 application에서 리턴받는 것임

 

삽질 과정 - 2: 결론

 - application code 수정은 진짜 정말 싫었지만 결국에 수정이 필수불가결...

 

위의 과정에 대한 삽질 URL

 https://stackoverflow.com/questions/57797374/is-mybatis-enable-to-insert-all-and-return-sequenceusegeneratekeys-in-oracle/57805042#57805042

 

Is mybatis enable to insert all and return sequence(useGenerateKeys) in oracle?

I'm currently migrating from PostgreSQL to Oracle DBMS. but occur some problem. I wish to work "Insert all with sequence and return sequence to application using usegeneratekeys in mybatis." My

stackoverflow.com

http://www.gurubee.net/article/81896

 

Tibero insert all Sequence 질문 드립니다.

안녕하세요 현재 Tibero DB 포팅 작업을 진행하고 있습니다. 시퀀스가 있는 테이블에 insert all이 잘 되지 않아 도움 구하고자 게시물 남깁니다. m..

www.gurubee.net

해결 방안

 - 일단 나는 Spring 4.x 사용 중

 - Spring 기능 중 Profile과 Interface 활용해서 application code를 수정하기로 했음

 - Spring Bean 등록을 Component-Scan으로 하기 때문에 *Dao.class의 @Repository 어노테이션을 제거 했음

 - 코드는 아래와 같다.

 web.xml

	<!-- option:oracle/another -->
	<context-param>
	    <param-name>spring.profiles.active</param-name>
	    <param-value>oracle</param-value>
	</context-param>

root-context.xml(application-context.xml)

	<!-- =================================================================== -->
	<!-- Register Repository Beans(Data Access Object)                       -->
	<!-- =================================================================== -->
	<beans profile="oracle">
		<bean id="ICodeDao" class="***.dao.CodeOracleDao" />
		<bean id="***Dao" class="***.dao.***Dao" />
		<bean id="***Dao" class="***.dao.***Dao" />
		<bean id="***Dao" class="***.dao.***Dao" />
		<bean id="***Dao" class="***.dao.***Dao" />
	</beans>
	<beans profile="another">
		<bean id="ICodeDao" class="***.dao.CodeDao" />
		<bean id="***Dao" class="***.dao.***Dao" />
		<bean id="***Dao" class="***.dao.***Dao" />
		<bean id="***Dao" class="***.dao.***Dao" />
		<bean id="***Dao" class="***.dao.***Dao" />
	</beans>

service.class

@Resource
ICodeDao dao;

빌드 및 운영에서는 web.xml에서의 oracle/another를 지정하면 됨

 

고찰 1 (insert의 방법)

일단, application code를 수정해야해서 짜증났음;

 

우리가 왜 multiple insert를 하느냐를 집중해야한다. -> 성능 때문에

약 1년 전 아래와 같은 테스트를 했었다(auto commit = false).

해당 테스트는 건별 insert의 속도 비교이다.

 - single insert(prepared statement)

 - foreach multiple insert(mybatis)

 - bulk insert 

결과는 아래와 같다(간단한 내부 테스트이므로 JUnit의 메소드 실행 시간임). 

건별 3가지의 insert 속도 비교

1000건 부터 bulk insert가 효과를 봄 여튼 위의 테스트는 아래 URL 참고해서 작성함

http://blog.harawata.net/2016/04/bulk-insert-multi-row-vs-batch-using.html

 

Bulk insert (multi-row vs. batch) using JDBC and MyBatis

I have seen some developers are using multi-row insert in MyBatis to perform bulk insert. If performance is your concern, though, you shoul...

blog.harawata.net

 고찰 2 (prepared statement와 foreach insert)

일단 SQL에서 multiple insert한 이유는 다음과 같다.

application과 DBMS와의 1번의 Round Trip(1번의 네트워크)을 통해 성능 개선을 위했던거임

근데, 막상 1년 전의 테스트를 보니까 prepared statement로 insert하는게 더 나아보임;;ㅡㅡ

 

prepared statement의 경우, DBMS의 바인드 변수를 사용하니까 빠른 것 같음..

여기서 궁금한거는 prepared statement와 네트워크 대역폭이 궁금함.. << 이거는 다음에 알아봐야겠음

 

주저리주저리 끝.

저작자표시 비영리 (새창열림)

'개발관련 > 삽질' 카테고리의 다른 글

AOP(SpringAOP/AspectJ)  (0) 2019.12.02
AJP 프로토콜 모든 것을 분석 해보자  (1) 2019.10.28
JWT를 분석하고 사용해보자 (3/3)  (0) 2019.08.13
JWT를 분석하고 사용해보자 (2/3)  (0) 2019.08.13
JWT를 분석하고 사용해보자 (1/3)  (0) 2019.08.13
Posted by 동팡
블로그 이미지

https://github.com/ehdvudee

by 동팡

공지사항

    최근...

  • 포스트
  • 댓글
  • 트랙백
  • 더 보기

태그

  • 볼트란
  • Secret Sharing 이론
  • 개발자 책리뷰
  • 이직 느낀점
  • Hashicorp
  • java
  • 네이버 클라우드
  • Secret Sharing
  • Spring
  • 네이버 클라우드 이직
  • vault 개요
  • LoRaWA
  • 개발자 준비
  • 책리뷰
  • Thread-safe
  • vault tutorial
  • 하시콥 볼트
  • 네이버 클라우드 개발자 면접
  • Shamir Secret Sharing
  • 간단리뷰
  • 이직 정보 공유
  • 개발자 글쓰기 책
  • NBP
  • 네이버 비즈니스 플랫폼
  • 자바
  • What is Vault
  • 경력 채용
  • 개발자 이직
  • vault
  • 글쓰기 가이드

글 보관함

«   2025/07   »
일 월 화 수 목 금 토
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
27 28 29 30 31

링크

카테고리

메모장 (73)
개발관련 (71)
삽질 (26)
(과거)메모 (27)
강의 (0)
회고 (9)
책 리뷰 (9)
블로그 관리 글(비공개) (0)
일상 (2)
기타 (0)
책 리뷰 (1)
회고 (0)

카운터

Total
Today
Yesterday
방명록 : 관리자 : 글쓰기
동팡's Blog is powered by daumkakao
Skin info material T Mark3 by 뭐하라
favicon

메모장

https://github.com/ehdvudee

  • 태그
  • 링크 추가
  • 방명록

관리자 메뉴

  • 관리자 모드
  • 글쓰기
  • 메모장 (73)
    • 개발관련 (71)
      • 삽질 (26)
      • (과거)메모 (27)
      • 강의 (0)
      • 회고 (9)
      • 책 리뷰 (9)
    • 블로그 관리 글(비공개) (0)
    • 일상 (2)
      • 기타 (0)
      • 책 리뷰 (1)
      • 회고 (0)

카테고리

PC화면 보기 티스토리 Daum

티스토리툴바