2017-06-11 217 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

相关问题