자바 에서 JDBC 는 MySQL 에 백만 급 데 이 터 를 삽입 하 는 인 스 턴 스 코드 를 실현 합 니 다.

어떤 표 에 수백 만 개의 데 이 터 를 삽입 하여 테스트 를 하고 싶 습 니 다.원래 의 생각 은 10W 순환 을 해서 데 이 터 를 마음대로 삽입 해 보 세 요.좋 습 니 다.저 는 정말 순진 합 니 다.

DROP PROCEDURE IF EXISTS proc_initData;--            
DELIMITER $
CREATE PROCEDURE proc_initData()
BEGIN
  DECLARE i INT DEFAULT 1;
  WHILE i<=100000 DO
    INSERT INTO text VALUES(i,CONCAT('  ',i),'XXXXXXXXX');
    SET i = i+1;
  END WHILE;
END $
CALL proc_initData();
CALL proc 실행initData()후,원래 생각 했 는데 10W 조 의 데 이 터 를 30 분 정도 더 늦 추 면 해결 할 수 있 을 것 같 습 니 다.결국 저 는 LOL 2 개 를 친 후에 뒤 돌아 보 니 아직도 실행 되 고 있 습 니 다.이때 마음 이 완전히 멍 해 졌 습 니 다.제 가 세 번 째 데 이 터 를 다 친 후에 드디어 실 행 했 습 니 다.이런 방법 이 저 에 게 수백 만 개의 데 이 터 를 기다 리 게 한다 면 아침 에 출근 하고 오후 에 퇴근 해서 돌아 와 도 끝나 지 않 았 습 니까?10W 개의 데이터,그림 이 있 고 진실 이 있 습 니 다.

JDBC 데이터베이스 에 일반 삽입 방식
뒤 를 살 펴 보 니 JDBC 일괄 작업 으로 데이터베이스 에 100 W+의 데 이 터 를 삽입 하 는 것 도 빠 른 것 같 습 니 다.
먼저 JDBC 가 데이터베이스 에 보통 삽입 하 는 방식 을 말씀 드 리 겠 습 니 다.간단 한 코드 는 대체적으로 다음 과 같 습 니 다.1000 개 를 순환 하고 중간 에 무 작위 수 치 를 추 가 했 습 니 다.자신 이 데 이 터 를 가지 고 테스트 해 야 하기 때문에 데 이 터 는 모두 똑 같 고 구분 하기 어렵 습 니 다.

private String url = "jdbc:mysql://localhost:3306/test01";
  private String user = "root";
  private String password = "123456";
  @Test
  public void Test(){
    Connection conn = null;
    PreparedStatement pstm =null;
    ResultSet rt = null;
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection(url, user, password);    
      String sql = "INSERT INTO userinfo(uid,uname,uphone,uaddress) VALUES(?,CONCAT('  ',?),?,?)";
      pstm = conn.prepareStatement(sql);
      Long startTime = System.currentTimeMillis();
      Random rand = new Random();
      int a,b,c,d;
      for (int i = 1; i <= 1000; i++) {
          pstm.setInt(1, i);
          pstm.setInt(2, i);
          a = rand.nextInt(10);
          b = rand.nextInt(10);
          c = rand.nextInt(10);
          d = rand.nextInt(10);
          pstm.setString(3, "188"+a+"88"+b+c+"66"+d);
          pstm.setString(4, "xxxxxxxxxx_"+"188"+a+"88"+b+c+"66"+d);27           pstm.executeUpdate();
      }
      Long endTime = System.currentTimeMillis();
      System.out.println("OK,  :" + (endTime - startTime)); 
    } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }finally{
      if(pstm!=null){
        try {
          pstm.close();
        } catch (SQLException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
      if(conn!=null){
        try {
          conn.close();
        } catch (SQLException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
    }
  }
출력 결과:OK,사용 시간:738199,단위 밀리초,즉 이런 방식 은 직접 데이터베이스 에서 순환 하 는 것 과 차이 가 많 지 않다.
대량 처 리 를 논의 하기 전에 만 나 는 구 덩이 를 먼저 말 해 보 세 요.먼저 JDBC 가 연 결 된 url 에 rewriteBatched Statements 인 자 를 true 로 설정 하 는 것 이 대량 작업 의 전제 입 니 다.그 다음 에 my sql 드라이버 를 검사 할 때 5.1.13 이상 버 전(이 버 전보 다 지원 되 지 않 음)입 니 다.인터넷 에서 5.1.7 버 전 을 임의로 다운로드 한 다음 에 대량 작업(100 W 항목 삽입)을 수행 합 니 다.그 결과 드라이브 버 전이 너무 낮 아서 지원 되 지 않 아 자바 프로그램 을 중단 한 후에 도 my sql 은 데이터베이스 에 데 이 터 를 계속 삽입 하고 있 습 니 다.마지막 으로 데이터베이스 서 비 스 를 중단 해 야 합 니 다.
그렇다면 낮은 버 전의 드라이버 패 키 지 는 100 W+데 이 터 를 삽입 하면 무력 합 니까?실제로 또 다른 방식 이 있 는데,효율 에 비해 서 는 그래도 받 아들 일 수 있다.
트 랜 잭 션 제출 방식 사용
먼저 명령 의 제출 방식 을 false 로 설정 합 니 다.즉,conn.setAutoCommit(false)을 수 동 으로 제출 합 니 다.마지막 으로 모든 명령 이 실 행 된 후에 사무 conn.comit()를 제출 합 니 다.

private String url = "jdbc:mysql://localhost:3306/test01";
  private String user = "root";
  private String password = "123456";
  @Test
  public void Test(){
    Connection conn = null;
    PreparedStatement pstm =null;
    ResultSet rt = null;
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection(url, user, password);    
      String sql = "INSERT INTO userinfo(uid,uname,uphone,uaddress) VALUES(?,CONCAT('  ',?),?,?)";
      pstm = conn.prepareStatement(sql);
      conn.setAutoCommit(false);
      Long startTime = System.currentTimeMillis();
      Random rand = new Random();
      int a,b,c,d;
      for (int i = 1; i <= 100000; i++) {
          pstm.setInt(1, i);
          pstm.setInt(2, i);
          a = rand.nextInt(10);
          b = rand.nextInt(10);
          c = rand.nextInt(10);
          d = rand.nextInt(10);
          pstm.setString(3, "188"+a+"88"+b+c+"66"+d);
          pstm.setString(4, "xxxxxxxxxx_"+"188"+a+"88"+b+c+"66"+d);
          pstm.executeUpdate();
      }
      conn.commit();
      Long endTime = System.currentTimeMillis();
      System.out.println("OK,  :" + (endTime - startTime)); 
    } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }finally{
      if(pstm!=null){
        try {
          pstm.close();
        } catch (SQLException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
      if(conn!=null){
        try {
          conn.close();
        } catch (SQLException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
    }
  }
상기 코드 는 10W 개의 데 이 터 를 삽입 하고 출력 결과:OK,사용 시간:18086,즉 18 초 정도 의 시간 입 니 다.이론 적 으로 100 W 즉 3 분 입 니 다.이렇게 하면 겨우 받 아들 일 수 있 습 니 다.
일괄 처리
다음은 일괄 처리 입 니 다.5.1.13 이상 버 전의 드라이버 백 이 필요 합 니 다.

private String url = "jdbc:mysql://localhost:3306/test01?rewriteBatchedStatements=true";
  private String user = "root";
  private String password = "123456";
  @Test
  public void Test(){
    Connection conn = null;
    PreparedStatement pstm =null;
    ResultSet rt = null;
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection(url, user, password);    
      String sql = "INSERT INTO userinfo(uid,uname,uphone,uaddress) VALUES(?,CONCAT('  ',?),?,?)";
      pstm = conn.prepareStatement(sql);
      Long startTime = System.currentTimeMillis();
      Random rand = new Random();
      int a,b,c,d;
      for (int i = 1; i <= 100000; i++) {
          pstm.setInt(1, i);
          pstm.setInt(2, i);
          a = rand.nextInt(10);
          b = rand.nextInt(10);
          c = rand.nextInt(10);
          d = rand.nextInt(10);
          pstm.setString(3, "188"+a+"88"+b+c+"66"+d);
          pstm.setString(4, "xxxxxxxxxx_"+"188"+a+"88"+b+c+"66"+d);
          pstm.addBatch();
      }
      pstm.executeBatch();
      Long endTime = System.currentTimeMillis();
      System.out.println("OK,  :" + (endTime - startTime)); 
    } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }finally{
      if(pstm!=null){
        try {
          pstm.close();
        } catch (SQLException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
      if(conn!=null){
        try {
          conn.close();
        } catch (SQLException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
    }
  }
10W 출력 결과:OK,사용 시간:3386,겨우 3 초.
일괄 작업+트 랜 잭 션
그리고 대량 작업+트 랜 잭 션 제출 하면?신기 효과 가 있 지 않 을까요?

private String url = "jdbc:mysql://localhost:3306/test01?rewriteBatchedStatements=true";
  private String user = "root";
  private String password = "123456";
  @Test
  public void Test(){
    Connection conn = null;
    PreparedStatement pstm =null;
    ResultSet rt = null;
    try {
      Class.forName("com.mysql.jdbc.Driver");
      conn = DriverManager.getConnection(url, user, password);    
      String sql = "INSERT INTO userinfo(uid,uname,uphone,uaddress) VALUES(?,CONCAT('  ',?),?,?)";
      pstm = conn.prepareStatement(sql);
      conn.setAutoCommit(false);
      Long startTime = System.currentTimeMillis();
      Random rand = new Random();
      int a,b,c,d;
      for (int i = 1; i <= 100000; i++) {
          pstm.setInt(1, i);
          pstm.setInt(2, i);
          a = rand.nextInt(10);
          b = rand.nextInt(10);
          c = rand.nextInt(10);
          d = rand.nextInt(10);
          pstm.setString(3, "188"+a+"88"+b+c+"66"+d);
          pstm.setString(4, "xxxxxxxxxx_"+"188"+a+"88"+b+c+"66"+d);
          pstm.addBatch();
      }
      pstm.executeBatch();
      conn.commit();
      Long endTime = System.currentTimeMillis();
      System.out.println("OK,  :" + (endTime - startTime)); 
    } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }finally{
      if(pstm!=null){
        try {
          pstm.close();
        } catch (SQLException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
      if(conn!=null){
        try {
          conn.close();
        } catch (SQLException e) {
          e.printStackTrace();
          throw new RuntimeException(e);
        }
      }
    }
  }
다음은 100 W 데이터 출력 대비 입 니 다.(5.1.17 버 전 MySql 드라이버 에서 테스트 하고 두 가지 방식 으로 데이터 테스트 결 과 를 교체 합 니 다)
일괄 작업(10W)
일괄 작업+트 랜 잭 션 제출(10W)
일괄 작업(100 W)
일괄 오류+트 랜 잭 션 제출(100 W)
OK,사용 시간:3901
OK,사용 시간:3343
OK,사용 시간:44242
OK,사용 시간:39798
OK,사용 시간:4142
OK,사용 시간:2949
OK,사용 시간:44248
OK,사용 시간:39959
OK,사용 시간:3664
OK,사용 시간:2689
OK,사용 시간:44389
OK,사용 시간:39367
이 를 통 해 어느 정도 효율 이 향상 되 었 음 을 알 수 있 지만 뚜렷 하지 않다.물론 데이터 차이 가 그리 크 지 않 기 때문에 우연 한 인수 가 존재 할 수도 있다.왜냐하면 항목 당 3 번 만 측정 하기 때문이다.
사전 컴 파일+일괄 작업
인터넷 에 서 는 사전 컴 파일+대량 작업 방식 을 사용 하면 효율 을 높 일 수 있다 는 말 도 있 지만 본인 이 직접 측정 하면 효율 이 높 지 않 고 오히려 떨 어 지 는 것 은 테스트 데이터 와 관련 이 있 을 수 있 습 니 다.
사전 컴 파일 된 쓰기 방법 은 JDBC 연결 url 에 useServerPrepStmts=true 를 기록 하면 됩 니 다.
예:

 private String url = "jdbc:mysql://localhost:3306/test01?useServerPrepStmts=true&rewriteBatchedStatements=true"
 
 자,여기까지..
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기