MySQL Jdbc驱动的rewriteBatchedStatements参数

本文探讨了在MySQL数据库中批量添加、修改、删除功能的实现方式,通过设置rewriteBatchedStatements参数,优化批量操作性能。实验展示了参数开启前后,不同SQL操作(如批量删除、更新、插入)在性能上的显著提升。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意:在使用mysql 数据库的时候如果需要批量添加,修改,删除功能则要设置rewriteBatchedStatements参数,这样才能真正起到批量添加的功能

// 开启批量添加

private String url="jdbc:mysql://localhost:3306/music?rewriteBatchedStatements=true";   

// 关闭批量添加

private String url="jdbc:mysql://localhost:3306/music?rewriteBatchedStatements=false";  

MySQL Jdbc驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,直接造成较低的性能。


只有把rewriteBatchedStatements参数置为true,驱动才会帮你批量执行SQL (jdbc:mysql://ip:port/db?rewriteBatchedStatements=true)。不过,驱动具体是怎么样批量执行的?

 

另外,有人说rewriteBatchedStatements只对INSERT有效,有人说它对UPDATE/DELETE也有效。为此我做了一些实验(详见下文),结论是:这个选项对INSERT/UPDATE/DELETE都有效,只不过对INSERT它为会预先重排一下SQL语句


实验记录:未打开rewriteBatchedStatements

未打开rewriteBatchedStatements时,根据wireshark嗅探出的mysql报文可以看出,

batchDelete(10条记录)  =>  发送10delete请求

batchUpdate(10条记录)  =>  发送10update请求

batchInsert(10条记录)  =>  发送10insert请求

 

也就是说,batchXXX()的确不起作用

 

实验记录:打开了rewriteBatchedStatements

打开rewriteBatchedStatements后,根据wireshark嗅探出的mysql报文可以看出

 

batchDelete(10条记录)  =>  发送一次请求,内容为”delete from t where id = 1; delete from t where id = 2; delete from t where id = 3; ….”

batchUpdate(10条记录)  =>  发送一次请求,内容为”update t set … where id = 1; update t set … where id = 2; update t set … where id = 3 …”

batchInsert(10条记录)  =>   发送一次请求,内容为”insert into t (…) values (…) , (…), (…)”

 

deleteupdate,驱动所做的事就是把多条sql语句累积起来再一次性发出去;而对于insert,驱动则会把多条sql语句重写成一条风格很酷的sql语句,然后再发出去。官方文档说,这种insert写法可以提高性能(”This is considerably faster (many times faster in some cases) than using separate single-row INSERT statements”

 

一个注意事项

需要注意的是,即使rewriteBatchedStatements=true, batchDelete()batchUpdate()也不一定会走批量:batchSize <= 3时,驱动会宁愿一条一条地执行SQL。所以,如果你想验证rewriteBatchedStatements在你的系统里是否已经生效,记得要使用较大的batch.

 

 

对应的代码

最后可以看下对应的MySQL  JDBC驱动的代码,以加深印象:

 

clip_image002[4]

 

 


结论:

  1. PreparedStatement ps = conn.prepareStatement(  
  2.    "INSERT into employees values (?, ?, ?)");  
  3.   
  4. for (n = 0; n < 100; n++) {  
  5.   
  6.   ps.setString(name[n]);  
  7.   ps.setLong(id[n]);  
  8.   ps.setInt(salary[n]);  
  9.   ps.addBatch();  
  10. }  
  11. ps.executeBatch();

1、如果不开启 rewriteBatchedStatements 则即使是使用了批量添加也不起作用。

2、批量不仅仅对insert 其作用,也对update和delete 起作用。

3、驱动默认是关闭批量功能的,所以在使用的时候 要手动开启。

4、所以在写url时要注意写全:

url=jdbc:mysql://localhost:3306/music?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull



### 如何在MySQL 8.0 JDBC批处理中正确配置Properties文件的URL参数 在使用MySQL 8.0进行JDBC编程时,为了实现高效的数据操作,通常会采用批量更新的方式。而在这种场景下,`Properties`文件中的`url`参数需要特别注意其配置方式和细节。 #### URL 参数说明 对于MySQL 8.0的JDBC连接字符串,推荐使用的URL格式如下所示[^1]: ```plaintext spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=UTC&useSSL=false ``` 此URL包含了多个重要的查询参数: - `useUnicode=true`: 启用Unicode编码支持。 - `characterEncoding=utf8mb4`: 设置字符集为UTF-8扩展版本utf8mb4,适合存储emoji表情等特殊字符。 - `serverTimezone=UTC`: 明确指定服务器所在的时区,防止因本地与远程时间不一致引发问题。 - `useSSL=false`: 关闭SSL加密连接,适用于开发环境或不需要安全传输的情况。 如果是在批处理模式下,则还需要额外关注以下几个参数: - `rewriteBatchedStatements=true`: 开启该选项可以显著提升批处理性能,允许驱动程序优化SQL语句的发送方式[^2]。 完整的URL可能看起来像这样: ```plaintext jdbc:mysql://localhost:3306/db_demo?useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true ``` #### Properties 文件配置方法 当通过`Properties`对象传递连接属性时,可以通过以下方式进行设置: ##### 示例代码 下面是一个基于`Properties`对象完成批处理的例子[^3]: ```java import java.sql.*; import java.util.Properties; public class JDBCBatchProcessingExample { public static void main(String[] args) throws Exception { // 加载并注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 定义数据库连接信息 String url = "jdbc:mysql://localhost:3306/db1"; // 创建Properties实例 Properties props = new Properties(); props.setProperty("user", "root"); props.setProperty("password", "111"); props.setProperty("useSSL", "false"); props.setProperty("serverTimezone", "UTC"); props.setProperty("rewriteBatchedStatements", "true"); // 批量处理优化开关 try (Connection conn = DriverManager.getConnection(url, props); Statement stmt = conn.createStatement()) { // 添加多条SQL到批处理队列 stmt.addBatch("INSERT INTO grades VALUES(1, 'Alice', 95)"); stmt.addBatch("INSERT INTO grades VALUES(2, 'Bob', 88)"); stmt.addBatch("INSERT INTO grades VALUES(3, 'Charlie', 76)"); // 执行批处理 int[] counts = stmt.executeBatch(); // 输出每条SQL影响的行数 for (int count : counts) { System.out.println("受影响的行数:" + count); } } catch (SQLException e) { e.printStackTrace(); } } } ``` 在这个例子中,`Properties`对象被用来保存用户名、密码以及其他必要的连接参数。其中的关键在于设置了`rewriteBatchedStatements=true`来启用批处理优化功能[^4]。 #### 注意事项 1. **驱动兼容性**: 确保已导入正确的MySQL Connector/J驱动版本(建议至少为8.x),因为不同版本间可能存在API差异[^5]。 2. **安全性考量**: 生产环境中应避免硬编码敏感数据如用户名和密码;可考虑使用外部化配置工具或者密钥管理服务替代明文形式。 3. **异常捕获**: 始终围绕数据库交互逻辑添加全面的错误捕捉机制,以便及时发现潜在隐患。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值