2013-12-12 2 views
3

간단한 자바 콘솔 응용 프로그램에서 PreparedStatement을 사용하여 InputStream에서 방대한 양의 데이터를로드합니다. 내가 일괄 처리를 실행하고있어최적화 방대한 양의 데이터가 포함 된 INSERT

public void readStopTimes(CSVReader reader) throws IOException, SQLException { 
     String insertSql = "INSERT INTO stop_times VALUES (null, ?, ?, ?, ?, ?)"; 
     PreparedStatement statement = db.prepareStatement(insertSql); 
     String [] nextLine; 
     long i = 0; 
     Chronometer chronometer = new Chronometer(); 
     while ((nextLine = reader.readNext()) != null) { 
      if(i++ != 0) { 
       statement.setString(1, nextLine[0]); 
       if(nextLine[1].isEmpty()) 
        statement.setNull(2, Types.TIME); 
       else 
        statement.setTime(2, Time.valueOf(nextLine[1])); 
       if(nextLine[2].isEmpty()) 
        statement.setNull(3, Types.TIME); 
       else 
        statement.setTime(3, Time.valueOf(nextLine[2])); 
       statement.setString(4, nextLine[3]); 
       statement.setInt(5, Integer.parseInt(nextLine[4])); 
       statement.addBatch(); 
      } 
      if(i++ % 1000 == 0) { 
       statement.executeBatch(); 
      } 
      if(chronometer.count() > 5000) { 
       chronometer.restart(); 
       log.debug("Analyzed {} rows", i); 
      } 
     } 
     statement.executeBatch(); 
     db.commit(); 
    } 

마다 1,000 삽입, 5 초마다 내가 로그를 인쇄하고 있습니다 :

는 코드입니다.

로그에서 알 수 있듯이이 알고리즘은 처음에는 매우 빠르며 처음 25 초 동안 총 4 백만 개가 넘는 행을 계산 한 다음 5 초 만에 2 행만 도착하면 속도가 느려집니다 배치에 추가되었습니다.

5 백만 개가 넘는 행을 삽입해야합니다. 더 빠른 대안이 있습니까? MySQL의

  • innodb_flush_log_at_trx_commit = 2 또는 당신이 당신의 mysql을 만드는 것보다 충돌하지 않도록 할 수있는 경우에

  • +0

    답을 모르겠지만 테스트를 위해 : statement.executeBatch();'뒤에'statement = db.prepareStatement (insertSql);을 추가 할 수 있습니까? –

    답변

    1
    • 비활성화 쿼리 캐시 그것을 innodb_flush_log_at_trx_commit = 0
    • 복제 sync_binlog = 0
    • 을 수행하여 빈 로그의 동기화를 해제보다 활성화 된 경우

    당신은 직접 Load data infile . . . . . 명령으로 MySql에 CSV 파일을 넣을 수 있습니다.이 명령은 꽤 빠릅니다.

    +0

    올바른 솔루션은 데이터 infile을로드하고 결국 java로 파일을 미리 파싱하는 것입니다. –

    0

    statement.executeBatch(); 끝이 아니라. 이것은 mysql이 insert에 탭을 유지하면서 계속 진행할 때 insert가 플러시되도록 허용해야한다. 그래서 필요하다면 모두 되돌릴 수있다.

    +0

    안타깝게도 작동하지 않았습니다. –

    0

    단일 배치 대신 여러 배치로 데이터를 추가하십시오. 모든 배치 후에 커밋하고 처리 된 데이터를 추적합니다. 또는 스테이징 테이블을 사용하여 테이블에 데이터를 추가하고 완료되면 테이블의 이름을 바꾸거나, 실패한 경우 다시 시작하거나, 저장 지점에서 다시 시작하거나 시작할 수 있습니다.

    관련 문제