JDBC的批量批量插入
本文部分转载于:http://blog.itpub.net/29254281/viewspace-1151785/
http://www.cnblogs.com/chenjianjx/archive/2012/08/14/2637914.html (这篇文章作者用的mysql驱动是5.1.12)
一. JDBC的批量插入
1.Mysql的驱动jar包选择(重要)
使用MySQL的Batch批量处理,驱动jar包版本需要5.1.13或以上 我使用的驱动版本:mysql-connector-java-5.1.18-bin (一开始我忽略掉这个jar包的条件要求了,使用的是mysql-connector-java-5.1.6-bin.jar在批处理插入时候效率和普通一样)
2.测试表结构
测试表结构如下:
CREATE TABLE test (
id int(11) DEFAULT NULL,
name varchar(20) DEFAULT NULL
) ENGINE=InnoDB
3.首先使用普通的方式插入100万条数据,使用时间154901毫秒
程序如下:
1 public static void generalInsert() throws ClassNotFoundException,SQLException{ 2 long start = System.currentTimeMillis(); 3 Class.forName("com.mysql.jdbc.Driver"); 4 Connection connection = DriverManager.getConnection( 5 "jdbc:mysql://127.0.0.1:3306/kxh", "root", "root"); 6 7 connection.setAutoCommit(false); 8 PreparedStatement cmd = connection 9 .prepareStatement("insert into test values(?,?)"); 10 11 for (int i = 0; i < 1000000; i++) { 12 cmd.setInt(1, i); 13 cmd.setString(2, "test"); 14 cmd.executeUpdate(); 15 } 16 connection.commit(); 17 18 cmd.close(); 19 connection.close(); 20 21 long end = System.currentTimeMillis(); 22 System.out.println(end - start);//158918毫秒 23 }
4.使用批量处理100万条数据,仅用24675毫秒,提升效果非常明显,提升了6倍多.
程序如下:
1 public static void batchInsert() throws ClassNotFoundException, SQLException{ 2 long start = System.currentTimeMillis(); 3 Class.forName("com.mysql.jdbc.Driver"); 4 Connection connection = DriverManager.getConnection( 5 "jdbc:mysql://127.0.0.1:3306/kxh?useServerPrepStmts=false&rewriteBatchedStatements=true", 6 "root", "root"); 7 8 connection.setAutoCommit(false); 9 PreparedStatement cmd = connection 10 .prepareStatement("insert into test1 values(?,?)"); 11 12 for (int i = 0; i < 1000000; i++) {//100万条数据 13 cmd.setInt(1, i); 14 cmd.setString(2, "test"); 15 cmd.addBatch(); 16 if(i%1000==0){ 17 cmd.executeBatch(); 18 } 19 } 20 cmd.executeBatch(); 21 connection.commit(); 22 23 cmd.close(); 24 connection.close(); 25 26 long end = System.currentTimeMillis();
27 System.out.println("批量插入需要时间:"+(end - start)); //批量插入需要时间:24675 28 }
MySQL 的驱动jar包在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,直接造成较低的性能。
与Oracle不同的是,Mysql需要添加rewriteBatchedStatements=true的参数,才可以使用批量处理,否则还是使用逐条处理的方式。另外,有人说rewriteBatchedStatements只对INSERT有效,有人说它对UPDATE/DELETE也有效。
通过试验结论是: 这个选项对INSERT/UPDATE/DELETE都有效,只不过对INSERT它为会预先重排一下SQL语句。
5.开启Myslq的查询日志
①批量插入的日志:
开启MySQL的查询日志general_log(关于如何打开,查看mysql的日志请查看博客:http://www.cnblogs.com/DreamDrive/p/5761005.html),发现如下SQL
INSERT INTO test VALUES (11, 'test'), (12, 'test'), (13, 'test')......
上下两行的id号码正好相差1000,也就是代码中设置的每1000次提交一次批处理.
②普通插入对应的日志:
如果使用普通的插入打印日志如下:
相对Oracle的批量处理,MySQL需要JDBC参数显式开启,并且对于JDBC驱动的版本也有要求。
参数useServerPrepStmts=false,如果不开启(useServerPrepStmts=false),使用com.mysql.jdbc.PreparedStatement进行本地SQL拼装,最后送到db上就是已经替换了?后的最终SQL.
作者:SummerChill 出处:http://www.cnblogs.com/DreamDrive/ 本博客为自己总结亦或在网上发现的技术博文的转载。 如果文中有什么错误,欢迎指出。以免更多的人被误导。 |