728x90
반응형
기존에 5분에 한번씩 데이터를 인서트해주는 Agent가 말썽을 부려서 무려 1개월 분량의 데이터를 재처리해야 된다고 한다.
하루치 데이터만 700만건.
기존의 Agent는 5분에 한번씩 기동하기 때문에 단건으로 Insert 하여도 큰 문제가 없었으나, 에러 발생 이후로 재처리는 한달 분량을 insert 처리를 해야한다. 당연히 하루 700만건 30일치를 단건으로 insert 처리하면 속도가 안나온다.
소스 수정이 불가피했다.
기존의 Agent는 JDBC로 직접 연결해 DB에 인서트하고 있었다.
이를 addBatch와 executeBatch를 통해 해결하였다.
public static void insertDoneMsgDB(String tablename, DoneMessageVO done) {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String queryStr = String.format("REPLACE INTO %s %s", tablename, ADD_DONE_MSG);
DBConnectionMgr db = DBConnectionMgr.getInstance();
try{
//������������ ��������
con = db.getConnection();
pstmt = con.prepareStatement(queryStr);
pstmt.setString(1, done.getSystem());
pstmt.setString(2, done.getMsg_seq_id());
pstmt.setString(3, done.getReal_user_submit_time());
pstmt.setString(4, done.getUser_id());
pstmt.setString(5, done.getCompany_name());
pstmt.setString(6, done.getAgent_id());
pstmt.setInt(7, done.getAgent_type());
pstmt.setInt(8, done.getSvc_type());
pstmt.setString(9, done.getCarrier_id());
pstmt.setString(10, done.getCarrier_cid());
pstmt.setString(11, done.getMachine_id());
pstmt.setString(12, done.getReal_carrier_id());
pstmt.setString(13, done.getRecv_mdn());
pstmt.setString(14, done.getCall_mdn());
pstmt.setString(15, done.getCarrier_tid());
pstmt.setString(16, done.getAsp_id());
pstmt.setInt(17, done.getIs_050());
pstmt.setString(18,done.getCarrier_submit_time());
pstmt.setString(19, done.getCarrier_deliver_time());
pstmt.setString(20, done.getUser_deliver_time());
pstmt.setString(21, done.getCarrier_code());
pstmt.setString(22, done.getResult_code());
pstmt.setString(23, done.getCharging_id());
pstmt.setString(24, done.getCustomer_tid());
pstmt.setString(25, done.getContent_info());
pstmt.setString(26, done.getContent_size());
pstmt.setString(27, done.getNat_cd());
pstmt.executeUpdate();
DoneCntVo.total_cnt++;
DoneCntVo.success_cnt++;
} catch (Exception e){
logger.error(e.getMessage(), e);
logger.error("에러 : " + done.getMsg_seq_id() + " : done.getCompany_name : " + done.getCompany_name());
DoneCntVo.total_cnt++;
DoneCntVo.fail_cnt++;
}
finally {
//������������ ������������
db.freeConnection(con, pstmt, rs);
db.removeConnection(con);
}
}
public static void insertDoneMsgBatchDB(String tablename, List<DoneMessageVO> doneList) {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String queryStr = String.format("REPLACE INTO %s %s", tablename, ADD_DONE_MSG);
DBConnectionMgr db = DBConnectionMgr.getInstance();
try{
//������������ ��������
con = db.getConnection();
con.setAutoCommit(false);
pstmt = con.prepareStatement(queryStr);
for(DoneMessageVO doneVo : doneList) {
int i = 0;
pstmt.setString(1, doneVo.getSystem());
pstmt.setString(2, doneVo.getMsg_seq_id());
pstmt.setString(3, doneVo.getReal_user_submit_time());
pstmt.setString(4, doneVo.getUser_id());
pstmt.setString(5, doneVo.getCompany_name());
pstmt.setString(6, doneVo.getAgent_id());
pstmt.setInt(7, doneVo.getAgent_type());
pstmt.setInt(8, doneVo.getSvc_type());
pstmt.setString(9, doneVo.getCarrier_id());
pstmt.setString(10, doneVo.getCarrier_cid());
pstmt.setString(11, doneVo.getMachine_id());
pstmt.setString(12, doneVo.getReal_carrier_id());
pstmt.setString(13, doneVo.getRecv_mdn());
pstmt.setString(14, doneVo.getCall_mdn());
pstmt.setString(15, doneVo.getCarrier_tid());
pstmt.setString(16, doneVo.getAsp_id());
pstmt.setInt(17, doneVo.getIs_050());
pstmt.setString(18,doneVo.getCarrier_submit_time());
pstmt.setString(19, doneVo.getCarrier_deliver_time());
pstmt.setString(20, doneVo.getUser_deliver_time());
pstmt.setString(21, doneVo.getCarrier_code());
pstmt.setString(22, doneVo.getResult_code());
pstmt.setString(23, doneVo.getCharging_id());
pstmt.setString(24, doneVo.getCustomer_tid());
pstmt.setString(25, doneVo.getContent_info());
pstmt.setString(26, doneVo.getContent_size());
pstmt.setString(27, doneVo.getNat_cd());
DoneCntVo.total_cnt++;
i++;
// addBatch에 담기
pstmt.addBatch();
// 파라미터 Clear
pstmt.clearParameters();
if( (i % 1000) == 0){
// Batch 실행
int batchCnt[] = pstmt.executeBatch() ;
// insert 성공 카운트
DoneCntVo.success_cnt += batchCnt.length;
// Batch 초기화
pstmt.clearBatch();
// 커밋
con.commit() ;
}
}
// Batch 실행
int batchCnt[] = pstmt.executeBatch();
// insert 성공 카운트
DoneCntVo.success_cnt += batchCnt.length;
// Batch 초기화
pstmt.clearBatch();
// 커밋
con.commit() ;
}
catch (Exception e){
con.rollback();
logger.error(e.getMessage(), e);
}
finally {
//������������ ������������
db.freeConnection(con, pstmt, rs);
db.removeConnection(con);
}
}
addBatch()로 쿼리를 메모리에 올린다.
executeBatch()로 쿼리를 전송한다.
executeBatch() 성공하면 clearBatch() 후 커밋
executeBatch()로 처리해야할 쿼리의 양이 많으면 부하를 먹을 것으로 생각하여 executeBatch()할 쿼리는 1000건으로 세팅하였다.
700만건 대상으로 10시간 걸리던 처리 속도가 2시간으로 확 줄었다..
더 줄이는 방법에 대해 생각해봐야겠다.
728x90
반응형
'IT > WEB' 카테고리의 다른 글
[https 오류] Mixed content this request has been blocked the content must be served over https (0) | 2022.05.24 |
---|---|
[JAVA] executeBatch 예외 처리 해결 (에러 무시하고 인서트) (1) | 2022.05.19 |
[JAVA] Mybatis insert foreach(foreach로 마이바티스 대량 insert 구현) (0) | 2022.05.17 |
[JS] Select Box 에서 readonly 설정하기 (0) | 2022.04.22 |
java.lang.ArrayIndexOutOfBoundsException: 1 에러 split() NULL 처리, 예외 처리 (0) | 2021.11.15 |