본문 바로가기

[Database] Mybatis 다량 Row 한번에 Insert 하는 법

곰곰킴 2022. 12. 8.

개요

10만번의 insert를 할 경우 232초가 걸렸다. 10만번의 DB I/O 시간 때문인데, UX관점에서 좋지 않았다.

I/O 횟수 단축을 위해 다량의 데이터를 한 번에 insert하는 방법을 찾았다.

방법 1

insert의 values 구문에 여러 개의 데이터 Row를 넣는다.

기존

insert into dataset
(ID, FIRSTNAME, LASTNAME, EMAIL)
values
(1, "Gomgom", "Kim", "abc@naver.com")

다중 insert

insert into dataset
(ID, FIRSTNAME, LASTNAME, EMAIL)
values
(1, "Gomgom", "Kim", "abc@naver.com"),
(2, "Gomgom2", "Kim", "abc2@naver.com"),
(3, "Gomgom3", "Kim", "abc3@naver.com"),
(4, "Gomgom4", "Kim", "abc4@naver.com"),
(5, "Gomgom5", "Kim", "abc5@naver.com")

다중 insert Mybatis 표현

<insert id="insertMultiRow" parameterType="java.util.Map">
    insert into dataset
    <trim prefix="(" suffix=")" suffixOverrides=",">
        ID, FIRSTNAME, LASTNAME, EMAIL
    </trim>
    values
    <foreach collection="multiData" item="item" separator=",">
        <trim prefix="(" suffix=")">
            #{item.id,jdbcType=VARCHAR},
            #{item.firstname,jdbcType=VARCHAR},
            #{item.lastname,jdbcType=VARCHAR},
            #{item.email,jdbcType=VARCHAR}
        </trim>
    </foreach>
</insert>

 

주의점

10만개의 데이터 row를 SQL문으로 붙이다 보니

Database 처리 과정에서 mybatis query memory exceeded가 발생했다.

Memory를 늘리는 방법도 있지만 데이터 갯수가 몇 개 까지 늘어날 지 모르는 상황이어서

확실한 해결책은 아니었다.

결론적으로 1만개 까지는 Insert가 되었고,

1만개씩 끊어서 저장하는 방법으로 구현하게 되었다.

반응형

방법 2

SqlSessionFactory 이용

//쿼리 호출하는 서비스단(기존 소스에서 sqlSessionFactory 부분 외에는 다 생략)

@Autowired
private SqlSessionFactory sqlSessionFactory;

private void test(){
	
    SqlSession sqlSession = null;
    sqlSession = this.SqlSessionFactory.openSession(ExecutorType.BATCH);
        
	while(!startCal.equals(endCal)){
        
        sqlSession.insert("com.test.hubjob.dao.StatBatchDao.insertList", voList); //실행할 쿼리를 insert 해둠.
        loopCnt++;

        //sqlSession 1일단위로 flush(1일 = 144건)
        if(loopCnt % 144 == 0) {
            sqlSession.flushStatements(); //한번에 밀어넣으면 오래걸리므로 적당한 간격으로 끊어서 밀어넣음.
        }
    }
    
    sqlSession.flushStatements(); //남은거 밀어넣고
    sqlSession.commit();	//커밋!(이때 커넥션 한번!)

}

 

 

댓글