250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- mssql
- MessageQueue
- 자동배포
- rabbitmq
- spring
- ORM
- Stream
- Jenkins
- DevOps
- QueryDSL
- 제이쿼리그리드
- 자바8
- 자동빌드
- sqlserver
- poi
- 보안
- 그리드
- JPA
- jqGrid
- apache.poi
- 스트림
- JQuery
- stream api
- java
- docker
- Javascript
- 대용량 업로드
- ci/cd
- mom
- 엑셀 업로드
Archives
- Today
- Total
개발 메모장
[Java] Apache.POI 엑셀 업로드 구현 - DB 처리(3/3) 본문
728x90
#. 엑셀 파일을 데이터화하는 작업은 처리했으나 DB에 insert 하는 속도 문제 또한 중요합니다.
#. Service에서 myBatis를 이용해 DB접근하는 for문으로 처리해보려 했으나 이 또한 DB 접근을 건마다 해야 하므로 좋은 방법은 아니라는 생각이 들었습니다.(1000건에 360초)
#. 오라클의 Insert all과 foreach를 이용해보려 했으나 이 또한 시간이 오래 걸렸습니다.(1000건에 7초)
#. 벌크 인서트의 경우 PL/SQL에서만 사용가능하다 보니 이 또한 적절하지 않다고 생각했습니다.
#. DB 처리 로직 구현
- 업로드할 데이터의 수는 약 20만 건으로 고정적인 데이터라 그 이상이 될 일은 거의 없었습니다.
- 여러 가지로 구현해 보고 테스트해봤을 때 가장 효과가 좋다고 생각한 addBatch를 통해 처리하였습니다.
- 분명 더 좋은 퍼포먼스를 보여주는 방법도 있을 것이지만 혼자 서치 및 구현하는 데에 시간적 제한이 있었습니다.
- 더 좋은 방법이 있다면 꼭 댓글 부탁드립니다!
@Transactional
public void addBatch(List<String> headers, List<HashMap<String, String>> postData) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql = "insert into 테이블명 values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
try {
Class.forName("net.sf.log4jdbc.sql.jdbcapi.DriverSpy");
// DB 연결
conn = DriverManager.getConnection("jdbc:log4jdbc:oracle:thin:@IP주소:포트번호:SID", "접속 ID", "비밀번호");
pstmt = conn.prepareStatement(sql);
// AutoCommit 해제
conn.setAutoCommit(false);
int i = 0;
// sql 변수에 들어갈 내용을 꺼내어 셋팅 및 처리
for(HashMap<String, String> postDatum:postData) {
// 변수 번호 / 데이터 반복 처리
for(int j = 0; j < headers.size(); j++) {
pstmt.setString(j + 1, postDatum.get(headers.get(j)));
}
pstmt.addBatch();
pstmt.clearParameters();
i++;
// 5000건 단위 수동 커밋
if((i%5000)==0) {
pstmt.executeBatch();
pstmt.clearBatch();
conn.commit();
}
}
// 5000건 외 나머지 처리
pstmt.executeBatch();
conn.commit();
} catch (Exception e) {
e.printStackTrace();
try {
conn.rollback();
throw e;
} catch (SQLException e1) {
e.getStackTrace();
throw e1;
}
} finally {
// 자원 반환
if(pstmt != null) { try {pstmt.close();pstmt = null; } catch (SQLException e) { e.getStackTrace();}}
if(conn != null) { try {conn.close();conn = null; } catch (SQLException e) { e.getStackTrace();}}
}
}
#. 처리 속도 이슈
- 구현 예제와는 다르게 실제 데이터의 행 개수는 약 50개이다 보니 속도 문제가 중요했었습니다.
- 서두에 적어놨지만 1000건 처리에 시간이 꽤나 소요되었으나 위와 같이 처리 후 테스트 해 본 결과 1000건에 1초도 걸리지 않았습니다.
- 다만 건수가 많아지면 많아질수록 데이터를 메모리에 올리는 작업에 들어가는 시간이 길어졌습니다.
- 약 20만 건의 데이터를 인서트 하는 데에 총 2분 정도 소요되는 걸 확인하였습니다.
- 실질적인 인서트 작업 이전에 메모리에 올리는 작업의 속도를 더 챙겨줄 수 있는 방법을 알았다면 조금 더 만족했을 텐데 아쉬운 부분이 있습니다.
- 추후 시간적 여유가 생긴다면 해당 부분을 수정해 보도록 하겠습니다.
===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================
728x90
'Java' 카테고리의 다른 글
[Java] 함수형 인터페이스(Functional Interface) (0) | 2024.06.13 |
---|---|
[Java] keytool을 이용한 루트 인증서 등록(SSLHandshakeException) (0) | 2024.04.18 |
[Java] Apache.POI 엑셀 업로드 구현 - Controller(2/3) (2) | 2024.01.04 |
[Java] Apache.POI 엑셀 업로드 구현 - Handler(1/3) (1) | 2024.01.03 |
[Java] 로그 구성하기 - Slf4j(logback, Log4j ...) (1) | 2023.12.19 |