250x250
Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- Exception
- MSSQL
- maven
- MySQL
- Open Source
- jpa
- Docker
- JavaScript
- Python
- Source
- ubuntu
- error
- Spring Boot
- spring
- 문서
- Thymeleaf
- git
- AJAX
- PostgreSQL
- SpringBoot
- oracle
- Eclipse
- 설정
- Core Java
- JDBC
- myBatis
- IntelliJ
- STS
- 오픈소스
- Tomcat
Archives
- Today
- Total
헤르메스 LIFE
[iBatis] iBatis에서 batch 기능 활용하기 본문
728x90
원문 : http://fantazic.com/page/47
iBatis는 아래와 같은 방법으로 batch 처리가 가능하다. iBatis 내부 코드를 확인해 본 바로는 PreparedStatement.addBatch()를 사용하고 있고, 동일한 쿼리가 반복해서 들어올 때 하나의 batch로 처리해준다.
try { SqlMapClient.startTransaction(); SqlMapClient.startBatch(); while (...) { SqlMapClient.insert(query, params); } SqlMapClient.executeBatch(); SqlMapClient.commitTransaction(); } catch (Exception e) { log.error(e, e); } finally { SqlMapClient.endTransaction(); }
이 기능을 활용해서 BatchManager를 만들어서 사용하고 있는데, 사용자의 로그인 시간을 기록하거나 게시물의 조회수를 늘리는 등 빈번하게 동일한 update가 발생하는 서비스에 사용하면 효과가 있다.
사용법은 기존의 서비스 코드 수정을 최소화하는 방법으로 고안했다. SqlMapClient.insert(query, params)를 BatchManager.insert(query, params)로 수정하면 된다.
관련 코드)
BatchManager.java
public class BatchManager { private static BatchWorker worker = BatchWorker.getInstance(); static { Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { try { worker.flushAll(); worker.stop(); } catch (Exception e) { e.printStackTrace(); } } }); } public static void insert(String query, Object params) { worker.put(new BatchQuery(INSERT, query, params)); } public static void update(String query, Object params) { worker.put(new BatchQuery(UPDATE, query, params)); } }BatchWorker.java
public class BatchWorker { public static final int HEARTBEAT = 1000; public static int MAX_WAIT = 30000; public static final int SIZE_OF_ONE_BATCH = 200; public static final int MAX_SIZE = 100; private long lastTime; private final Timer timer; private Vectorqueue; private static BatchWorker singletonWorker; private BatchWorker() { lastTime = System.currentTimeMillis(); timer = new Timer(true); queue = new Vector (); startWorker(); } public static synchronized BatchWorker getInstance() { if (singletonWorker == null) singletonWorker = new BatchWorker(); return singletonWorker; } private void startWorker() { timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { try { doBatch(); } catch (Exception e) { // ignore e.printStackTrace(); } } }, 0, HEARTBEAT); } private void doBatch() { if (System.currentTimeMillis() - lastTime > MAX_WAIT || queue.size() >= MAX_SIZE) { executeQuery(); lastTime = System.currentTimeMillis(); } } private synchronized void executeQuery() { if (queue.size() == 0) return; try { int cnt = 0; SqlMapClient.startTransaction(); SqlMapClient.startBatch(); while (cnt++ < SIZE_OF_ONE_BATCH) { if (queue.size() == 0) break; BatchQuery batchQuery = queue.remove(0); switch (batchQuery.type) { case INSERT: SqlMapClient.insert(batchQuery.query, batchQuery.params); break; case UPDATE: SqlMapClient.update(batchQuery.query, batchQuery.params); break; default: break; } } SqlMapClient.executeBatch(); SqlMapClient.commitTransaction(); } catch (Exception e) { log.error(e, e); } finally { SqlMapClient.endTransaction(); } } public int size() { return queue.size(); } public void put(BatchQuery query) { queue.add(query); } public void flushAll() { while (queue.size() > 0) executeQuery(); } public void stop() { timer.cancel(); } } BatchQuery.java
public class BatchQuery { public enum QueryType { INSERT, UPDATE } public String query; public Object params; public QueryType type; public BatchQuery(QueryType type, String query, Object params) { this.type = type; this.query = query; this.params = params; } }
참고)
- Oracle10g 환경에서는 batch로 처리할 경우 쿼리 수행은 빨라지나 batch 처리마다 쿼리 파싱이 발생해서 CPU 비용은 증가하는 경우도 보였다.
- 예전에 찾아본 바로는 한번에 만건 이상도 batch 처리가 가능하다고 한다. 환경에 따라 가장 효율적인 batch 크기를 결정해야 한다.
- batch 처리할 경우 수행속도가 빨라지는 장점이 있고 transaction lock이 적게 잡혀 DB 부담을 줄여주는 효과도 있다.
728x90
'Spring Framework' 카테고리의 다른 글
[Open Source] Send Mail + 첨부파일 포함 (0) | 2011.09.22 |
---|---|
[Open Source] Thread를 통한 Mail 발송 (0) | 2011.09.22 |
[Spring] 웹 어플리케이션에 SpringSecurity 2.0.X 를 적용하기 (0) | 2010.11.04 |
[iBatis] iBatis의 쿼리로그 변경 (0) | 2010.10.27 |
[iBatis] iBatis 2.3.4.726 Build (0) | 2010.10.26 |