JAVA对MYSQL数据库进行批量操作,addBatch(),executeBatch()方法

最近要做一个批处理插入数据的,但是试了批处理的代码发现没有效果,很纳闷啊。但是之前在学习JDBC操作Mysql批处理的时候,记得要在数据库url中的参数加配置的,但是忘了。网速搜居然不容易搜出来,我也是醉了,难道这么重要的参数都不重视?于是就看到这一篇,感谢博主。至于这个参数就是“rewriteBatchedStatements=true”这个对批处理很大影响,没有它就相当于没有批处理。


有人说MySQL的JDBC驱动,不是真正支持批量操作的,就算你在代码中调用了批量操作的方法,MySql的JDBC驱动也是按照一般操作来处理的。

但其实并非如此,Mysql 是有特殊的方式优化整个batch insert 结果的。

可不可以先假设 batch 的方式与非batch一样,每一条insrt语句事实上均是单独发往服务器的呢?

浏览下源代码吧。 

好多兄弟都描述了源代码,直接从那几个类入手吧,事实上关键的类是这个 com.mysql.jdbc.PreparedStatement 

先看了其中的 addBatch 方法,没有任何问题,只是将语句添加进入一个 List 中保存。 

那么 executeBatch 呢? 

再贴一下吧, 关键看其中的这部分,顺带说一下, 这个mysql-jdbcdriver的源代码是 5.1.13的 

[java]  view plain  copy
  1. try {     
  2.     clearWarnings();     
  3.     
  4.     if (!this.batchHasPlainStatements     
  5.             && this.connection.getRewriteBatchedStatements()) {     
  6.              
  7.              
  8.         if (canRewriteAsMultiValueInsertAtSqlLevel()) {     
  9.             return executeBatchedInserts(batchTimeout); //执行路径之一     
  10.         }     
  11.              
  12.         if (this.connection.versionMeetsMinimum(410)      
  13.                 && !this.batchHasPlainStatements     
  14.                 && this.batchedArgs != null      
  15.                 && this.batchedArgs.size() > 3 /* cost of option setting rt-wise */) {     
  16.             return executePreparedBatchAsMultiStatement(batchTimeout); //执行路径之二     
  17.         }     
  18.     }     
  19.     
  20.     return executeBatchSerially(batchTimeout); //执行路径之三     
  21. finally {     
  22.     clearBatch();     
  23. }   

其实最终,executeBatch 的执行路径有三种可能。代码中我已标出来 


代码不算太复杂,但是有一个参数能帮助我们更快的确定mysql的batch工作机制,那就是 
mysql jdbc driver 的connection url, 其中有一个参数是: rewriteBatchedStatements
 

完整的参数参考看这里:http://ftp.ntu.edu.tw/ftp/pub/MySQL/doc/refman/5.1/en/connector-j-reference-configuration-properties.html

rewriteBatchedStatements 参数默认为false, 需要手工设置为true,设置方式大概像这样:

[java]  view plain  copy
  1. String connectionUrl="jdbc:mysql://192.168.1.100:3306/test?rewriteBatchedStatements=true";      

默认时候,rewriteBatchedStatements=false时,执行路径会跳到 executeBatchSerially,此方法内部将语句一条条发送,与非batch处理简直一样,所以慢,就在这里了。

当设为 true时,会执行executeBatchedInserts方法,事实上mysql支持这样的插入语句

[sql]  view plain  copy
  1. insert into t_user(id,uname) values(1, '1'), (2,'2'), (3, '3') ....    

针对rewriteBatchedStatements=true 参数我做了测试,我加了这个参数,做同们的插入10万条记录测试: 
我的mysql 安装的虚拟机上,所以慢一些。 
MySql JDBC 驱动版本结果
5.0.8没有提高 18秒
5.1.7没有提高 18秒
5.1.13有提高 1.6秒

所以Mysql的批量操作一定要加上MySql连接的url中要加rewriteBatchedStatements参数设为true。


最后贴下代码:

public static void batchSave() {
		new Thread() {
			public void run() {
				long start = System.currentTimeMillis();
				Connection conn = null;
				PreparedStatement pstmt = null;
				try {
					String sql = "insert into bluetooth_code_raw(rawCode, md5Code) values(?,?)";
					conn = db1.conn;
					// JAVA默认为TRUE,我们自己处理需要设置为FALSE,并且修改为手动提交,才可以调用rollback()函数
					conn.setAutoCommit(false);
					pstmt = conn.prepareStatement(sql);
					for (int i = 0; i < 100000; i++) {
						String gunCode = MagicCodeUtil.generateGunCode(0, i);

						pstmt.setString(1, gunCode);
						pstmt.setString(2, MagicCodeUtil.getMd5(gunCode));
						pstmt.addBatch();
						//防止内存溢出,我也不是很清楚都这么写
						if ((i + 1) % 1000 == 0) {
							pstmt.executeBatch();
							pstmt.clearBatch();
						}
					}
					pstmt.executeBatch(); // 批量执行
					conn.commit();// 提交事务
				} catch (SQLException e) {
					try {
						conn.rollback(); // 进行事务回滚
					} catch (SQLException ex) {
						e.printStackTrace();
					}
				} finally {
					if (pstmt != null)
						try {
							pstmt.close();
						} catch (SQLException e) {
							e.printStackTrace();
						}
					if (conn != null)
						try {
							conn.close();
						} catch (SQLException e) {
							e.printStackTrace();
						}
				}
				System.out.println((System.currentTimeMillis() - start) / 1000);
			};
		}.start();
	}


Java中实现MySQL数据库批量更新可以使用JDBCJava Database Connectivity)来完成。以下是一种常见的实现方式: 1. 首先,你需要导入JDBC相关的库文件,例如MySQL Connector/J。 2. 在Java代码中,你需要建立与数据库的连接。可以使用`java.sql.Connection`类来创建一个连接对象,并通过`DriverManager.getConnection()`方法传入数据库的URL、用户名和密码来获取连接。 3. 创建一个`java.sql.Statement`对象,用于执行SQL语句。 4. 使用`addBatch()`方法将多个SQL语句添加到批处理中。例如,你可以使用`UPDATE`语句来更新多条记录。 5. 调用`executeBatch()`方法执行批处理中的所有SQL语句。 6. 最后,记得关闭连接和释放资源。 下面是一个简单的示例代码: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class BatchUpdateExample { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydatabase"; String username = "root"; String password = "password"; try (Connection connection = DriverManager.getConnection(url, username, password); Statement statement = connection.createStatement()) { // 设置自动提交为false,开启事务 connection.setAutoCommit(false); // 添加多个SQL语句到批处理 statement.addBatch("UPDATE mytable SET column1 = value1 WHERE id = 1"); statement.addBatch("UPDATE mytable SET column1 = value2 WHERE id = 2"); statement.addBatch("UPDATE mytable SET column1 = value3 WHERE id = 3"); // 执行批处理 int[] updateCounts = statement.executeBatch(); // 提交事务 connection.commit(); System.out.println("更新记录数:" + updateCounts.length); } catch (SQLException e) { e.printStackTrace(); } } } ``` 请注意,上述代码中使用了事务(Transaction)来确保批量更新的原子性,即要么全部更新成功,要么全部回滚。你可以根据实际需求进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值