2017-06-11 14 views
0

jdbcバッチ更新が非常に遅い理由について、インターネット+ stackoverflow全体で読んできました。適切な修正が接続文字列にrewriteBatchedStatements = trueを設定するように見えます。しかし、私はそれが私のために働くように感じることはできません。私はspringbootと春-JDBC私も?rewriteBatchedStatements=trueことを確認するために、ブレークポイントを設定しているmysql jdbc rewriteBatchedStatements = trueの後でも照会をバッチしない

spring.datasource.url=jdbc:mysql://RDS_URL.us-west-2.rds.amazonaws.com/DATABASE?rewriteBatchedStatements=true 

アイブ氏は私のapplication.propertiesでrewriteBatchedStatements = trueを設定を使用しています

は私がgeneral_logいる

コードに反映されていますtrueに設定し、ログを見ると、挿入が適切にバッチ処理されていないことがわかります

これは私のSQL文字列の外観です

012ログに

private static String INSERT_USER_TO_GROUP_SQL = "INSERT INTO users (groupId, phoneNumber, accountId, source) VALUES(?, ?, ?, ?)";

行はすべて、この

45 Query INSERT INTO users (groupId, phoneNumber, accountId, source) VALUES('49', '99999999999', '123', 'web')

ように見えるバッチ挿入を行うには私のJavaコードは、ここで

executor.submit(() -> { 
    jdbcTemplate.batchUpdate(INSERT_USER_TO_GROUP_SQL, new BatchPreparedStatementSetter() { 

    @Override 
    public void setValues(PreparedStatement ps, int i) throws SQLException { 
     Subscriber subscriber = subscribers.get(i); 
     ps.setString(1, subscriberGroup.getGroupId()); 
     ps.setString(2, subscriber.getPhoneNumber()); 
     ps.setString(3, accountId); 
     ps.setString(4, subscriberGroup.getSource()); 
    } 

    @Override 
    public int getBatchSize() { 
     return subscribers.size(); 
    } 

    }); // end BatchPreparedStatementSetter lambda class 
}); // end thread 

あるメソッドからの抜粋ですbatchUpdateこのように見えますが、addBatch()を呼び出してから、最後にexecuteBatch()を呼び出します。

ここでは
for (int i = 0; i < batchSize; i++) { 
    pss.setValues(ps, i); 
    if (ipss != null && ipss.isBatchExhausted(i)) { 
     break; 
    } 
    ps.addBatch(); 
} 
return ps.executeBatch(); 

私は

CREATE TABLE `users` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `phoneNumber` varchar(20) DEFAULT NULL, 
    `groupId` varchar(11) DEFAULT NULL, 
    `source` varchar(30) DEFAULT NULL, 
    `accountId` varchar(50) DEFAULT NULL, 
    `deleted` int(1) DEFAULT '0', 
    `timestamp` datetime DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `phoneNumber` (`phoneNumber`,`groupId`,`accountId`) 
) ENGINE=InnoDB AUTO_INCREMENT=21677 DEFAULT CHARSET=latin1; 

に挿入しています表には、私も(jdbc.batchUpdateに依存する)と、それを自分でやっていない試してみました。まだ運

Connection connection = jdbcTemplate.getDataSource().getConnection(); 
    connection.setAutoCommit(false); 
    PreparedStatement preparedStatement = 
    connection.prepareStatement(INSERT_USER_TO_GROUP_SQL); 

    preparedStatement.setString(1, "1"); 
    preparedStatement.setString(2, "2"); 
    preparedStatement.setString(3, "3"); 
    preparedStatement.setString(4, "4"); 
    preparedStatement.addBatch(); 

    preparedStatement.setString(1, "11"); 
    preparedStatement.setString(2, "22"); 
    preparedStatement.setString(3, "33"); 
    preparedStatement.setString(4, "44"); 
    preparedStatement.addBatch(); 

    preparedStatement.executeBatch(); 
    connection.commit(); 

も私にはハードコーディングクエリを試してみましたので、準備された文の問題を排除しようとしたん。まだ運がありません。

Connection connection = jdbcTemplate.getDataSource().getConnection(); 
Statement statement = connection.createStatement(); 
statement.addBatch("INSERT INTO users (groupId, phoneNumber, accountId, source) VALUES('1', '2', '3', '4')"); 
statement.addBatch("INSERT INTO users (groupId, phoneNumber, accountId, source) VALUES('11', '22', '33', '44')"); 
statement.executeBatch(); 

これは私のポンポンでのJDBCのバージョン

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-jdbc</artifactId> 
    <version>1.5.2.RELEASE</version> 
</dependency> 

<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-jdbc</artifactId> 
    <version>4.3.6.RELEASE</version> 
</dependency> 

イム挿入をスピードアップするために、このパラメータを期待して、ログが正しくバッチ処理insert文を表示するためです。ほとんどのSOの記事は、URLにrewritebatchedstatements = trueと設定するだけの人々を示しています。私のバッチ書き込みが1に起こったので、私は

<dependency> 
     <groupId>mysql</groupId> 
     <artifactId>mysql-connector-java</artifactId> 
     <version>5.1.9</version> 
</dependency> 

を持っていたこの質問を書いている時点で、あなたのpom.xml

であなたのmysql-connector-javaバージョンを確認rewriteBatchedStatements = trueを尊重ないjdbcTemplate接続URLの問題を持つ他の人のために

+0

この記事、特にクエリのパフォーマンスに関するセクションをお読みください。 http://meta.stackoverflow.com/a/271056/質問を編集して詳細をお知らせください。その間、自動コミットを有効にしているか、複数の 'INSERT'文をSQLの' BEGIN TRANSACTION'/'COMMIT'ブロックにラップしているかどうかを調べてください。 –

+0

ありがとうございます。私は本当に特定のクエリのパフォーマンスについて心配していないので、タイトルを編集した、それはちょうど挿入のようにすばやくする必要があり、私はこれは典型的な "なぜ私のクエリが遅い"質問だとは思わない rewritebatchedstatements = trueは尊重されておらず、正しくインサートをバッチ処理しません。 Iveはテーブル構造と自動コミットを追加し、現在は – qHack

+0

になっています。 'addBatch()'と 'executeBatch()'メソッドを使用するコードはどこですか?書き換えによるパフォーマンスの向上は、バッチを使用して複数行の挿入を行うことにより、データベースサーバによって実行される暗黙的な 'COMMIT'操作の数を削減することにあります。 'executeBatch()'を呼び出す前に、 'addBatch()'を何度も呼び出すのですか? https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#addBatch(java.lang.String) –

答えて

1

1つはバージョン5.1と思われます。9バッチ更新をサポートしていない、とspring docs

batchUpdateメ()で述べたようにフォールバックは - JDBCドライバがバッチ更新をサポートしていない場合、単一のステートメントに戻って、別の更新プログラムに分類されます。

これをバージョン5.1.18に変更すると、適切なバッチ更新が実行され、mysql一般ログで確認されました。

また、他に時間を節約できるバグもありました。バージョン5.1.23では、db urlにprofileSQL=trueが含まれるように設定すると、ドライバとprofileSQLにはbugがあります。

関連する問題