Mybatis 사용시 My-sql 대용량 데이터 Bulk Insert
이번 프로젝트에서 Oracle -> mysql 로 대용량데이터 이관 하는 프로세스가 있어
작업중 이슈사항 정리 해본다.
구글링 해서 찾아보면
Loop를 이용해서 단건씩 Insert 하는 것 보다 Multi Value로 Insert 하면 성능이 월등하게 뛰어나다고
예를들면
start transaction;
insert into tb_name (a, b, c) values (1, 2, 3);
insert into tb_name (a, b, c) values (1, 2, 3);
insert into tb_name (a, b, c) values (1, 2, 3);
commit transaction;
이것보다
insert into tb_name (a, b, c)
values (1, 2, 3), (4, 5, 6), (7, 8, 9);
이렇게 하라고
스프링 + Mybatis 프레임웤 에서는
<insert id="insertResultAll" parameterType="java.util.List">
insert into tb_name (a, b, c)
values
<foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
#{a},#{b},#{v}
</foreach>
</insert>
이런식으로 foreach 를 쓰라고 한다. 근데 이게 100만건을 넘어가는 순간 저 Loop 만드는데 시간이 더걸린다.
그래서 최종적으로 선택한 방법
Service 단에서 sql문을 String 형으로 만든 다음에 Dao에 던졌다
for (Data data : dataList) {
sqlStr = "'"+data.getData+"','"
<insert id="insertResultAll" parameterType="String">
insert into tb_name (a, b, c)
values (
${sqlText}
)
</insert>
#으로 하면 SQL DB 실행 시에 데이터로 바인딩
ex) strText = "데이터" 일경우 #{srtText} 는 '데이터'
$으로 하면 SQL 쿼리문 로드시에 데이터 바인딩
ex) strText = "데이터" 일경우 ${srtText} 는 데이터
이렇게 처리 되기때문에 $의 경우 Sql injection에 취약하다.
가급적이면 않쓰는게 좋음!
필자는 내부서버에서 만 쓰는 서비스라 사용