2017-06-11 216 views
0

我一直在閱讀關於爲什麼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即可。

+0

請仔細閱讀,特別是關於查詢性能的部分。 http://meta.stackoverflow.com/a/271056/然後請[編輯]你的問題提供更多信息。同時,請確定是否打開了autocommit,或者是否在SQL中的'BEGIN TRANSACTION' /'COMMIT'塊中包裝多個'INSERT'語句。 –

+0

謝謝你。我編輯標題,因爲我並不真正關心特定的查詢性能,它應該很快,因爲它只是一個插入,我不認爲這是一個典型的「爲什麼我的查詢很慢」問題 我更感興趣的是爲什麼rewritebatchedstatements = true並沒有被尊重,並正確地批量插入。我添加了表結構和自動提交,它的當前轉向 – qHack

+0

你的代碼使用'addBatch()'和'executeBatch()'方法在哪裏?重寫所帶來的性能增益來自使用批處理來執行多行插入,從而減少數據庫服務器執行的隱式「COMMIT」操作次數。在調用'executeBatch()'之前,你是否調用過'addBatch()'整個過程? https://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html#addBatch(java.lang.String) –

回答

1

對於有沒有履行rewriteBatchedStatements = true JdbcTemplate的連接URL的問題,別人在你pom.xml

檢查mysql-connector-java版本在寫這個問題我有

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

的時候由於我的批處理寫入正在發生一個由一個看來,版本5.1。9不支持批量更新,並作爲spring docs

BATCHUPDATE()注意回落 - 將回落到單獨的更新在單一聲明如果JDBC驅動程序不支持批量更新。

將此版本反彈到版本5.1.18給了我正確的批量更新,在mysql通用日誌中進行了驗證。

另外一個我遇到的問題可能會節省一些時間。在版本5.1.23中,當您將數據庫url配置爲包含profileSQL=true(我認爲它最常用)時,驅動程序和profileSQL會有一個bug

相關問題