맵리듀스에서 리듀스 출력결과를 RDBMS로 저장 시 GC overhead limit exceeded Issue가 발생한다.
해당 Issue는 리듀스 출력결과가 즉 RDBMS로 저장되어야 하는 데이터가 많은 경우 발생하게 된다.
맵리듀스에서 RDBMS로 Insert하기 위해 org.apache.hadoop.mapreduce.lib.db.DBOutputFormat(링크)를
사용한다. 해당 소스를 까보면 리듀스 출력결과로 Insert문자열을 생성하여 addBatch()로 보관 후 DB Connection이 close될때 executeBatch()가 실행되고 commit()이 실행된다. 즉 대량의 데이터가 한번에 Insert되는 것이다.
해당 Issue와 관련해서 Cloudera블로그에도 관련 글이 존재한다. (링크)
이 문제를 해결하기 위해 DBOutputFormat을 상속받아 삽질을 했으나 해결방법은 의외로 간단하다.
public static final int batchSize = 5000; public static int count = 0; public static class DBOutputWritable implements Writable, DBWritable { String col1, col2; public DBOutputWritable(String col1, String col2) { this.col1 = col1; this.col2 = col2; } public void readFields(DataInput in) throws IOException {} public void readFields(ResultSet rs) throws SQLException { col1 = rs.getString(1); col2 = rs.getString(2); } public void write(DataOutput out) throws IOException {} public void write(PreparedStatement ps) throws SQLException { ps.setString(1,col1); ps.setString(2,col1); if(++count % batchSize == 0) { ps.executeBatch(); count=0; } } }DBOutputWritable에서 write메소드에서 데이터 단위를 나누어 주면된다.
끝.
'java' 카테고리의 다른 글
AWS JAVA SDK를 이용한 EMR(Elastic MapReduce) Job Flow 생성 및 실행 (0) | 2014.08.01 |
---|---|
S3 전체 파일 리스트 가져오기 (3) | 2014.07.28 |
[Effective Java] private 생성자를 사용해서 인스턴스 생성을 못하게 하자 (0) | 2014.01.23 |