[자바, iBatis 배치활용]insert/update 속도 개선!
새로운 이슈가 생겨서 블로그에 적어두려고 합니다.
일반 적으로 데이터를 insert, update를 할때 시간을 신경쓰지 않습니다.
그런데 이번 프로젝트를 진행하며
데이터 insert 할 건수가 대략 적이지만 50만건 정도는 되었습니다.
아무생각없이 일반 insert문으로 진행 할시 시간이 어마어마하게 많이 걸렸습니다.
1,000건을 insert해도 시간이 상당하더군요.
그래서 대용량 insert 등 막 검색해서
배치! 라는 것을 알게 되었습니다.
먼저 startBatch(), excuteBatch()함수를 활용해야 하는데
SqlMapExecutor 인터페이스에서 가져온 설명 입니다.
/**
* Starts a batch in which update statements will be cached before being sent to
* the database all at once. This can improve overall performance of updates update
* when dealing with numerous updates (e.g. inserting 1:M related data).
*
* @throws java.sql.SQLException If the batch could not be started.
*/
void startBatch() throws SQLException;
/**
* Executes (flushes) all statements currently batched.
*
* @return the number of rows updated in the batch
* @throws java.sql.SQLException If the batch could not be executed or if any of the statements
* fails.
*/
int executeBatch() throws SQLException;
startBatch() 를 보시면....제가 정확히 해석은 못하나 이해한 뜻은 이렇습니다.
insert, update 구문을 데이타 베이스로 한번에 모아서 보낸다...뭐 이런뜻...?
그래서 속도향상에 도움을 줄수있다!
그리고
excuteBatch() 이것은...
모아뒀던 구문을 한번에 실행한다!
뭐 이런 뜻을 파악하고 있습니다.
그럼 이제 실제 사용했던 소스를 첨부하겠습니다.
public Object batchInsertData(final ArrayList<Map> list, final String data_gb, final String new_doc_no, final String del_yn, final String query) throws Exception { // ibatis의 SqlExecutor을 사용 return getSqlMapClientTemplate().execute( new SqlMapClientCallback<Object> () { int totalCount = list.size(); // 전체 데이터의 건수 @Override public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException { try { // 배치처리 시작 executor.startBatch (); Map eachData; for (int idx = 0; idx < totalCount; idx++) { eachData = list.get(idx); eachData.put("data_gb", data_gb); eachData.put("data", data1); eachData.put("data2", data2); // 데이터 저장 executor.insert(query, eachData); dataCount++; // 저장건수 1000건 마다 배치 처리 if ((dataCount % 1000) == 0) { executor.executeBatch(); batchCount++; } } // 저장하지 않은 데이터 건수가 남아있다면 남은거 처리 if ((batchCount * 1000) < totalCount) { executor.executeBatch(); } } catch (Exception e) { throw new SQLException(e.getMessage()); }finally{ executor.executeBatch(); } return dataCount; } } ); }
간략하게 소스 설명을 드리자면!
저는 insnert 문을 적용시켰습니다.
insert문 전에 startBatch() 를 사용합니다.
그리고 excuteBatch()의 실행 시기는
1000건마다 실행되게 해두었습니다.
실행 결과 이전보다 거의 10배???
코드 실행 당시 실행시간도 체크했었는데 정확한 시간차이는 생각이 안나네요
결론적으로! 대용량 insert/update는 배치를 활용하시는 것을 추천합니다.
'개발 > java,spring' 카테고리의 다른 글
자바 가상머신(jvm) 메모리 모델, 개념 이해하기 (0) | 2017.09.24 |
---|---|
자바 선택정렬(select sort) (0) | 2017.09.16 |
이클립스를 통한 라이브러리 추가 및 jdk 버전 변경하기 (4) | 2017.09.08 |
스프링 @RequestBody, @ResponseBody (0) | 2017.07.07 |
자바 날짜형식, 데이트 타입/포맷 확인 (0) | 2017.07.05 |
도메인, VO 객체 Serializable 직렬화 (0) | 2017.06.13 |
스프링/아이바티스 2개의 DB연결 (0) | 2017.05.23 |