본문 바로가기

개발/DB

MyBatis 대량 데이터 INSERT - SqlSessionFactory 이용!

반응형

2022.02.21 - [개발/DB] - [Oracle] 대량 데이터 insert 하기. UNION ALL 사용.

 

[Oracle] 대량 데이터 insert 하기. UNION ALL 사용.

나의 상황 : 대량의 데이터를 테이블에 insert 해야하는 상황. (대부분 1000건 정도의 데이터지만 간혹 10000건 이상의 데이터도 insert 해야함.) 생각 과정 : 1. service 단에서 for 문을 이용하여 insert 요

jy-note.tistory.com

위의 이전에 작성한 글을 보면 대량 데이터를 insert 하기 위해 노력을 했었는데.. 몇 만건 정도는 끄떡없었지만 이번에 테스트 데이터를 3000만건을 넣고 돌렸더니 문제가 생겼다..슬퍼..

어쨋든 connection 이 여러번 생기니까 서버가 뻗는 문제가 발생..

더 좋은 방법을 알게되어 글을 추가하게 되었다!

-SqlSessionFactory 사용

> 기존에는 DAO 에서 쿼리를 호출할때마다 connection 이 생겼는데 SqlSessionFactory의 ExecutoryType.BATCH 를 사용하면 바로 DB 로 쿼리를 날리지 않고 쿼리를 미리 쌓아뒀다가  commit() 을 호출했을 때, 한번의 connection 에 모든 쿼리를 넘겨준다.

아래는 내가 사용한 방법이다.

//쿼리 호출하는 서비스단(기존 소스에서 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();	//커밋!(이때 커넥션 한번!)

}

 

+ 추가

나는 select 후 insert 를 하는 상황인데, select 문의 where 절에 있는 조건 값에 index도 걸어줬다. 이걸로 속도향상 된 게 젤 컸다!

 

반응형