[MySQL] Batch 및 Load 비교.

    MySQL에서 대용량의 데이터 처리를 하기 위해서 주로 쓰이는 두개의 방식인 Batch와 Load 방식에 대한 장단점을 비교하기로 한다. 어느 것이 무조건 좋다 나쁘다를 할 수 없기 때문에 어떤 상황에서 이 방식을 써야 할지 등을 알려보고자 한다.


    참고로, 필자가 다니는 회사는 전국민 상대로 서비스를 하고 있으며, 하루에도 몇십만명 이상이 사이트를 방문하기에 당연히 몇백만 이상의 로그가 쌓이고 있다. 데이터 분석을 한 결과(몇천만건 ~ 억단위)를 DB에 매일 배치 형태로 밀어 넣고 있는데 몇백에서 몇기가 단위의 데이터를 DB에 밀어 넣을 때는 늘 상 load(부하)를 잘 관리해야만 할 것이다.




    Batch 방식


    일단, 많이들 알고 있는 Batch 방식은 Insert를 Add 시킨 후, 한번에 커밋(commit) 하는 방식이다. 이 방식의 장점은 데이터를 핸들링 하기 편하다는 장점이 있다. 보통 데이터를 DB에 로드를 한다는 것은 꽤나 큰 부하이며, 부하가 가지 않는 선 내에서 적절하게 DB에 밀어 넣을 수 있는 장점이 있는데 서비스를 하는 DB에 무리가 간다면 load보다 Batch를 하는 방법이 좋을 것이다.


    소스예제

    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
    32
    33
    34
    35
    36
    37
    38
    // prepared로 처리
    Connection conn = null;
    PreparedStatement pstmt = null;
    int rc = 0;
     
    String sql = "조회쿼리";
     
    try {
        conn = getConnection();
        pstmt = conn.prepareStatement(query);
        conn.setAutoCommit(false);
        
        for(DicWrdClsVO vo : list) {
            pstmt.setString(1, vo.getTitle);
            pstmt.setString(2, vo.getWrdCls());
            pstmt.setString(3, vo.getSynm());
            pstmt.setString(4, vo.getRegUser());
            
            pstmt.addBatch();
            rc++;
        }
        
        pstmt.executeBatch();
        conn.setAutoCommit(true);
        pstmt.clearBatch();
        
    } catch (Exception e) {
        LOGGER.error("loadDic : " + e.getMessage());
        rc = -1;
    } finally {
        if (pstmt != null) {
            pstmt.close();
        }
     
        if (conn != null) {
            conn.close();
        }
    }
    cs



    Batch를 할 때는, iBatis 혹은 MyBatis같은 프레임워크를 사용하는 것보다 이렇게 Java Sample 소스처럼 코딩한 것을 넣는 것이 훨씬 편하고 빠르다. 예전에 iBatis로 배치 작업을 한 적이 있었지만, 속도면에서 차이가 심했었음.



    대용량일 경우, 위 방식에서 for문을 넣은 후, 10만건마다 setAutoCommit(true)등을 넣어주는 방식으로 처리를 해야 부하에 대한 핸들링이 원활할 것이다.



    Load 명령어


    MySQL에는 LOAD DATA라는 명령어를 지원하고 있는데 csv를 DB에 전송하는 것이다. 이 명령어를 자바로 코딩하여 DB에 직접 밀어넣을 경우, 첫번째 방식인 Batch 작업보다 월등히 빠른 속도를 느낄 수 있을 것이다. 다만 이렇게 할 경우, 대용량의 csv를 밀어 넣을 때, 부하에 대한 컨트롤이 힘든데 이럴 경우 csv를 잘게 쪼개서 넣으면 DB부하를 최소화 할 수 있다.


    소스예제

    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
    Connection conn = null;
    PreparedStatement pstmt = null;
     
    String filename = trinityVO.getServicePath() + "/" + fileNm;
     
    String sql = "LOAD DATA LOCAL INFILE \"" + filename + "\" INTO TABLE "
            + tableNm + " FIELDS TERMINATED BY \',\'" + fields;
     
    try {
        logger.info("load ... begin");
        
        conn = getDBConnection();
        pstmt = conn.prepareStatement(sql);
        
        conn.setAutoCommit(false);
        pstmt.executeUpdate();
        conn.setAutoCommit(true);
        
        pstmt.close();
        conn.close();
        
        logger.info("load...end");
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
    cs


    댓글

    Designed by JB FACTORY