본문 바로가기
Spring/DB_MyBatis

[ Mybatis / Spring ] foreach 구문을 이용해서 Insert 대량 삽입하기

by snow_hong 2022. 3. 15.

MyBatis에는 foreach 라는 것을 이용해서 Batch Insert를 할 수 있는 기능을 제공해줍니다.

foreach를 통해서 데이터를 INSERT 하는 것과 한 건씩 여러번 INSERT 하는 성능 차이가 얼마나 날까? 라는 생각을 할 수 있습니다.

저는 처음에 insert문을 만들때 한 건씩 등록하는 로직을 제작을 하였는데 137만건 정도의 insert를 두번이상하니깐 한 건씩 등록하는건 약 1시간 30분정도 걸리더라구요.

그래서 찾아보니깐 foreach를 이용해서 insert를 하면 성능이 좋다고 합니다.

foreach를 이용해서 insert를 한 것은 약 3분정도 걸렸어요. 약 30배 이상 차이가 나는 것을 볼 수 있었습니다.

* 성능 차이가 나는 이유

1. MyBatis 인터페이스 메소드 호출 -> Mapper id 검색 -> Query 수행 x 10000

간단히 말하면 위와 같이 MyBatis가 실행되는 과정, 쿼리 실행 모두의 과정이 만번이 발생하게 되는 것입니다. 시간이 많이 걸릴 수 밖에 없습니다.

2. MyBatis 인터페이스 메소드 호출 -> Mapper id 검색 과정이 1번만 실행되고 쿼리단에서만 만번이 실행되는 것입니다.  따라서 첫 번째보다 상대적으로 상당히 빠르게 INSERT 할 수 있습니다.

* 이제 예제를 통해서 foreach문 사용방법을 알아보자!

[java]

// 등록 예제
// DB에 있는 정보들을 가져와 insert하기
@Override
public Object putInfo(InfoVO vo) throws SQLException, ApiException, Exception {
	logger.info("====================== 등록 테스트[putInfo] ======================");
    
   int limit = 10000;
   String title = infoMapper.selectTitle(); //제목을 가져옴
	List<InfoVO> targetList = infoMapper.selectOncoTargetList(vo); //넣을 정보들을 가져옴
	List<List<InfoVO>> voTrgList = new ArrayList<List<InfoVO>>(); //만건씩 끊어서 넣을 list
	
//DB에 등록 시, 제목이 같다고 가정하고 제목을 동일하게 넣어두는 것
	for(int j=0; j<targetList.size(); j++) {
		targetList.get(j).setTitle(title);
	}
						
	// 10000건씩 list
	for(int i=0; i<targetList.size(); i+=limit) {
		voTrgList.add( targetList.subList(i, Math.min(i+limit, targetList.size()) ) );
	}
						
	// insert
	for(List<InfoVO> list : voTrgList) {
		// insert문 실행
		InfoMapper.insertTarget(list);
	}
}

==========================================================================
// service
public int insertTarget(List<InfoVO> list) throws SQLException, Exception;

 

[xml]

▶foreach문

- collection : 전달받은 인자. List or Array 형태만 가능

- item : 전달받은 인자 값을 alias 명으로 대체

- open : 구문이 시작될때 삽입할 문자열

- close : 구문이 종료될때 삽입할 문자열

- separator : 반복 되는 사이에 출력할 문자열

- index : 반복되는 구문 번호이다. 0부터 순차적으로 증가

<insert id="insertTarget" parameterType="java.util.List">
		INSERT INTO test_db.test01
		(test_sn, title , user_id)
		VALUES
		<foreach collection="list" item="infoVO" separator=",">
			(#{infoVO.testSn}::numeric, #{infoVO.title }, #{infoVO.userId})
		</foreach>
	</insert>

728x90

댓글