我一直在閱讀關於爲什麼jdbc批量更新太慢的internet + stackoverflow。看起來正確的解決方法是在連接字符串中設置rewriteBatchedStatements = true
。但我似乎無法讓它爲我工作。mysql jdbc即使在rewriteBatchedStatements = true之後也沒有批量查詢
我使用springboot和彈簧JDBC 伊夫設置在我application.properties rewriteBatchedStatements = true
spring.datasource.url=jdbc:mysql://RDS_URL.us-west-2.rds.amazonaws.com/DATABASE?rewriteBatchedStatements=true
我還設置一個斷點來驗證?rewriteBatchedStatements=true
體現在代碼
我已經general_log設置爲true,當看到日誌時,我看到插入沒有正確批處理
這是我的SQL字符串看起來像
個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的版本在我的POM
<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>
林希望這個參數來加快插入和日誌,以顯示正確批量插入語句。大多數SO文章顯示人們只需在網址中設置rewritebatchedstatements = true
即可。
請仔細閱讀,特別是關於查詢性能的部分。 http://meta.stackoverflow.com/a/271056/然後請[編輯]你的問題提供更多信息。同時,請確定是否打開了autocommit,或者是否在SQL中的'BEGIN TRANSACTION' /'COMMIT'塊中包裝多個'INSERT'語句。 –
謝謝你。我編輯標題,因爲我並不真正關心特定的查詢性能,它應該很快,因爲它只是一個插入,我不認爲這是一個典型的「爲什麼我的查詢很慢」問題 我更感興趣的是爲什麼rewritebatchedstatements = true並沒有被尊重,並正確地批量插入。我添加了表結構和自動提交,它的當前轉向 – qHack
你的代碼使用'addBatch()'和'executeBatch()'方法在哪裏?重寫所帶來的性能增益來自使用批處理來執行多行插入,從而減少數據庫服務器執行的隱式「COMMIT」操作次數。在調用'executeBatch()'之前,你是否調用過'addBatch()'整個過程? https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#addBatch(java.lang.String) –