使用JDBC连接MySQL数据库进行数据插入的时候,特别是大批量数据连续插入(10W+),如何提高效率呢?

在JDBC编程接口中Statement 有两个方法特别值得注意:

void addBatch() throws SQLException
Adds a set of parameters to this PreparedStatement object's batch of commands.
int[] executeBatch() throws SQLException
Submits a batch of commands to the database for execution and if all commands execute successfully, returns an array of update counts. The int elements of the array that is returned are ordered to correspond to the commands in the batch, which are ordered according to the order in which they were added to the batch. 
 
通过使用addBatch()和executeBatch()这一对方法可以实现批量处理数据。
 
不过值得注意的是,首先需要在数据库链接中设置手动提交,connection.setAutoCommit(false),然后在执行Statement之后执行connection.commit()。
  1. package cyl.demo.ipsearcher;
  2. import java.io.BufferedReader;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.InputStreamReader;
  6. import java.sql.Connection;
  7. import java.sql.DriverManager;
  8. import java.sql.PreparedStatement;
  9. import java.sql.SQLException;
  10. public class DbStoreHelper {
  11. private String insert_sql;
  12. private String charset;
  13. private boolean debug;
  14. private String connectStr;
  15. private String username;
  16. private String password;
  17. public DbStoreHelper() {
  18. connectStr = "jdbc:mysql://localhost:3306/db_ip";
  19. // connectStr += "?useServerPrepStmts=false&rewriteBatchedStatements=true";
  20. insert_sql = "INSERT INTO tb_ipinfos (iplong1,iplong2,ipstr1,ipstr2,ipdesc) VALUES (?,?,?,?,?)";
  21. charset = "gbk";
  22. debug = true;
  23. username = "root";
  24. password = "***";
  25. }
  26. public void storeToDb(String srcFile) throws IOException {
  27. BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile), charset));
  28. try {
  29. doStore(bfr);
  30. } catch (Exception e) {
  31. e.printStackTrace();
  32. } finally {
  33. bfr.close();
  34. }
  35. }
  36. private void doStore(BufferedReader bfr) throws ClassNotFoundException, SQLException, IOException {
  37. Class.forName("com.mysql.jdbc.Driver");
  38. Connection conn = DriverManager.getConnection(connectStr, username,password);
  39. conn.setAutoCommit(false); // 设置手动提交
  40. int count = 0;
  41. PreparedStatement psts = conn.prepareStatement(insert_sql);
  42. String line = null;
  43. while (null != (line = bfr.readLine())) {
  44. String[] infos = line.split(";");
  45. if (infos.length < 5)   continue;
  46. if (debug) {
  47. System.out.println(line);
  48. }
  49. psts.setLong(1, Long.valueOf(infos[0]));
  50. psts.setLong(2, Long.valueOf(infos[1]));
  51. psts.setString(3, infos[2]);
  52. psts.setString(4, infos[3]);
  53. psts.setString(5, infos[4]);
  54. psts.addBatch();          // 加入批量处理
  55. count++;
  56. }
  57. psts.executeBatch(); // 执行批量处理
  58. conn.commit();  // 提交
  59. System.out.println("All down : " + count);
  60. conn.close();
  61. }
  62. }
执行完成以后:
  1. All down : 103498
  2. Convert finished.
  3. All spend time/s : 47

一共10W+,执行时间一共花费 47 秒.

 
这个效率仍然不高,似乎没有达到想要的效果,需要进一步改进。
在MySQL JDBC连接字符串中还可以加入参数,
rewriteBatchedStatements=true,mysql默认关闭了batch处理,通过此参数进行打开,这个参数可以重写向数据库提交的SQL语句,具体参见:http://www.cnblogs.com/chenjianjx/archive/2012/08/14/2637914.html
useServerPrepStmts=false,如果不开启(useServerPrepStmts=false),使用com.mysql.jdbc.PreparedStatement进行本地SQL拼装,最后送到db上就是已经替换了?后的最终SQL.
 
在此稍加改进,连接字符串中加入下面语句(代码构造方法中去掉注释):
connectStr += "?useServerPrepStmts=false&rewriteBatchedStatements=true";
 
再次执行如下:
  1. All down : 103498
  2. Convert finished.
  3. All spend time/s : 10
同样的数据量,这次执行只花费了10秒 ,处理效率大大提高.

使用JDBC在MySQL数据库中快速批量插入数据的更多相关文章

  1. 在 SQL 中 快速 批量 插入数据的方法

    方法1:逐条执行,速度慢. INSERT INTO testimport (name, message) VALUES ('testname', 'jfksdfkdsfjksadljfkdsfjsdl ...

  2. 使用jdbc将mysql数据库中的内容封装为指定对象的list集合

    使用jdbc将mysql数据库中的内容封装为指定对象的list集合 public List<User> findAll() { private JdbcTemplate template ...

  3. net core天马行空系列-各大数据库快速批量插入数据方法汇总

    1.前言 hi,大家好,我是三合.我是怎么想起写一篇关于数据库快速批量插入的博客的呢?事情起源于我们工作中的一个需求,简单来说,就是有一个定时任务,从数据库里获取大量数据,在应用层面经过处理后再把结果 ...

  4. Java—JDBC向mysql数据库中给某个表添加数据时,会遇到的问题,如下

    解析(jar包该放在那里,以及其它的操作): 把jar包(驱动)添加到自己的项目中,最好新建一个文件夹,再把jar包(驱动包)添加到这个所新建的文件中 1.先建好自己的项目,再新建一个文件夹,如下: ...

  5. 通过java代码往mysql数据库中写入日期相关数据少13个小时

    通过show variables like '%time_zone%'; 查看时区: CST 时区 名为 CST 的时区是一个很混乱的时区,有四种含义: 美国中部时间 Central Standard ...

  6. 如何在MySQl数据库中给已有的数据表添加自增ID?

    由于使用MySQL数据库还没有多久的缘故,在搭建后台往数据库导入数据的时候发现新增的表单是没有自增id的,因次就有了上面这个问题. 解决方法 1.给某一张表先增加一个字段,这里我们就以node_tab ...

  7. ThinPHP3.2中 addAll()批量插入数据

    thinkphp中model类的addAll()方法可以将数据同时添加到数据库中. 1 2 3 4 5 6 // 批量添加数据 (only MySQL) $user = M('user'); //ar ...

  8. MySQL随机字符串函数批量插入数据

      简单举个例子: drop table if exists demo1 create table demo1 ( id int primary key auto_increment, name ) ...

  9. MariaDB快速批量插入数据的几种办法

    前言 当要向MariaDB中插入新的数据时,以下过程会影响插入所消耗的时间:(按时间消耗长短降序排序) 将数据sync到磁盘上(它是事务结束的一部分) 添加新的键值.索引越大,更新键值所消耗的时间就越 ...

随机推荐

  1. 关系操作符 == != equals()

    ==  和!= //: object/test.java package object; import java.util.*; public class Test{ public static vo ...

  2. python 全栈开发,Day115(urlencode,批量操作,快速搜索,保留原搜索条件,自定义分页,拆分代码)

    今日内容前戏 静态字段和字段 先来看下面一段代码 class Foo: x = 1 # 类变量.静态字段.静态属性 def __init__(self): y = 6 # 实例变量.字段.对象属性 # ...

  3. HBuilder支持jquery、zepto、angular、ext、dojo 等js框架的提示吗

    HBuilder有通行的js扫描分析提示,大部分js库都可以方便的提示.但js是一门超级灵活的语言,通行分析有时分析的不够完美,如果对框架做单独优化配置,可以有更好的提示.DCloud官方对jquer ...

  4. C# 关键字const与readonly的区别

    尽管你写了很多年的C#的代码,但是可能当别人问到你const与readonly的区别时候,还是会小小的愣一会吧~ 笔者也是在看欧立奇版的<.Net 程序员面试宝典>的时候,才发现自己长久以 ...

  5. Redis简单了解

    Redis介绍 Redis(REmote DIctionary Server)是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库, ...

  6. 安装Numpy方法

    Numpy安装(要先安装好python,见<windows下的python环境搭建(python2和python3不兼容,python2用的多)>) Numpy是Python的一个科学计算 ...

  7. for循环改为多线程方式进行执行

    import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class MySearchTe ...

  8. js获取按键

    event.altKey.event.ctrlKey.event.shiftKey 属性 属性为true表示事件发生时Alt.Ctrl.Shift键被按下并保持,为false则Alt.Ctrl.Shi ...

  9. pandas学习(创建多层索引、数据重塑与轴向旋转)

    pandas学习(创建多层索引.数据重塑与轴向旋转) 目录 创建多层索引 数据重塑与轴向旋转 创建多层索引 隐式构造 Series 最常见的方法是给DataFrame构造函数的index参数传递两个或 ...

  10. P2031 脑力达人之分割字串

    P2031 脑力达人之分割字串字符串dp,f[i]表示主串到第i个字符,最多能分割成多少子串.f[i]=max(f[i],f[k]+1);k是能匹配到的前一位. #include<iostrea ...