programing

JDBC 배치 삽입 성능

sourcejob 2022. 11. 24. 21:40
반응형

JDBC 배치 삽입 성능

mysql db에 수억 개의 레코드를 삽입해야 합니다.한 번에 100만 개씩 넣을 거예요아래 코드를 봐주세요.느린 것 같아요.최적화할 수 있는 방법이 있나요?

try {
        // Disable auto-commit
        connection.setAutoCommit(false);

        // Create a prepared statement
        String sql = "INSERT INTO mytable (xxx), VALUES(?)";
        PreparedStatement pstmt = connection.prepareStatement(sql);

        Object[] vals=set.toArray();
        for (int i=0; i<vals.length; i++) {
            pstmt.setString(1, vals[i].toString());
            pstmt.addBatch();
        }

        // Execute the batch
        int [] updateCounts = pstmt.executeBatch();
        System.out.append("inserted "+updateCounts.length);

mysql에서도 같은 퍼포먼스 문제가 발생하여 접속 URL에서 useServerPrepStmts 속성 및 rewriteBatchedStatements 속성을 설정하여 해결했습니다.

Connection c = DriverManager.getConnection("jdbc:mysql://host:3306/db?useServerPrepStmts=false&rewriteBatchedStatements=true", "username", "password");

접속 URL 파라미터에 대한 실험을 하고 있기 때문에 Bertil의 답변을 자세히 설명하겠습니다.

rewriteBatchedStatements=true는 중요한 파라미터입니다. useServerPrepStmts는 이미 false로 설정되어 있으며 true로 변경해도 배치 삽입 성능에 큰 차이가 없습니다.

이제 어떻게 하는지 써볼 때인 것 같아요.rewriteBatchedStatements=true퍼포먼스가 극적으로 향상됩니다.에 의해 그렇게 된다.rewriting of prepared statements for INSERT into multi-value inserts when executeBatch()(출처).즉, 다음을 보내는 대신n매번 mysql 서버에 대한 INSERT 문executeBatch()는 다음과 같습니다.

INSERT INTO X VALUES (A1,B1,C1)
INSERT INTO X VALUES (A2,B2,C2)
...
INSERT INTO X VALUES (An,Bn,Cn)

1 개의 INSERT 스테이트먼트를 송신합니다.

INSERT INTO X VALUES (A1,B1,C1),(A2,B2,C2),...,(An,Bn,Cn)

mysql 로깅을 켜면 확인할 수 있습니다.SET global general_log = 1각 문이 mysql 서버로 전송되는 파일에 로그인합니다.

하나의 insert 문을 사용하여 여러 행을 삽입할 수 있습니다.한 번에 수천 개의 작업을 수행하면 예를 들어 폼의 3개의 삽입을 수행하는 대신 작업 속도를 크게 높일 수 있습니다.INSERT INTO tbl_name (a,b,c) VALUES(1,2,3);,넌 그래.INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(1,2,3),(1,2,3);(JDBC.addBatch()도 비슷한 최적화를 하고 있습니다.mysql addBatch는 과거에 매우 최적화되어 있지 않고, 개개의 쿼리를 발행하고 있었습니다만, 최근의 드라이버에서는 아직 그러한지 어떤지 모르겠습니다.)

속도가 정말 필요한 경우 LOAD DATA INFILE을 사용하여 쉼표로 구분된 파일에서 데이터를 로드하면 수천만 개의 삽입을 수행하는 경우와 비교하여 속도가 약 7~8배 향상됩니다.

다음 경우:

  1. 새 테이블이거나 삽입할 양이 이미 삽입된 데이터보다 큽니다.
  2. 테이블 위에 색인이 있습니다.
  3. 삽입하는 동안 테이블에 다른 액세스 권한이 필요하지 않습니다.

그리고나서ALTER TABLE tbl_name DISABLE KEYS삽입 속도를 크게 향상시킬 수 있습니다.끝나면 달려라ALTER TABLE tbl_name ENABLE KEYS인덱스 작성을 시작할 수 있습니다.이 작업은 시간이 걸릴 수 있지만 모든 삽입에 대해 수행하는 것만큼 오래 걸리지는 않습니다.

DDBulkLoad 개체를 사용해 볼 수 있습니다.

// Get a DDBulkLoad object
DDBulkLoad bulkLoad = DDBulkLoadFactory.getInstance(connection);
bulkLoad.setTableName(“mytable”);
bulkLoad.load(“data.csv”);
try {
        // Disable auto-commit
        connection.setAutoCommit(false);
        int maxInsertBatch = 10000;     
        // Create a prepared statement
        String sql = "INSERT INTO mytable (xxx), VALUES(?)";
        PreparedStatement pstmt = connection.prepareStatement(sql);

        Object[] vals=set.toArray();
        int count = 1;
        for (int i=0; i<vals.length; i++) {
            pstmt.setString(1, vals[i].toString());
            pstmt.addBatch();
            if(count%maxInsertBatch == 0){
                 pstmt.executeBatch();
            }
            count++;
        }

        // Execute the batch
        pstmt.executeBatch();
        System.out.append("inserted "+count);

언급URL : https://stackoverflow.com/questions/2993251/jdbc-batch-insert-performance

반응형