使用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. k8s单机部署1.11.5

    一.概述 由于服务器有限,因此只能用虚拟机搭建 k8s.但是开3个节点,电脑卡的不行. k8s中文社区封装了一个 Minikube,用来搭建单机版,链接如下: https://yq.aliyun.co ...

  2. ireport 添加行自增序号

    ireport 添加行自增序号 在ireport报表中加入行的自增序号方法: 添加一个变量,如变量名为 index: 设置变量类型为Integer,计算类型为count:变量表达式为$V{index} ...

  3. ***LANMP镜像手册(Apache&Nginx)-lanmp-oneinstack

    LANMP镜像手册(Apache&Nginx) Version PHP7.0.26  转自:http://docs.websoft9.com/xdocs/lanmp-oneinstack-im ...

  4. Mysql 账号过期问题

    1.ALTER USER 'root'@'localhost' PASSWORD EXPIRE; 一旦某个用户的这个选项设置为”Y”,那么这个用户还是可以登陆到MySQL服务器,但是在用户未设置新密码 ...

  5. BZOJ5091 摘苹果 BZOJ2017年11月月赛 概率,期望

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ5091 11月月赛B题 题意概括 题解 代码 #include <cstring> #i ...

  6. Python - 常用更新命令以及常见库安装

    库的安装方式一般有两种: 一. pip直接安装(或使用豆瓣源) pip install scrapy pip install -i https://pypi.douban.com/simple/ sc ...

  7. 数据摘要 MD5

    数据一样,摘要一样  (摘要即MD5) 摘要一样,数据一样 摘要是用于检验数据的完整性的技术(比如验证下载的东西是否完整,迅雷就是这样), 查看文件的MD5: Linux         :  md5 ...

  8. 030.Zabbix分布式部署

    一 分布式Zabbix介绍 zabbix proxy 可以代替 zabbix server 收集性能和可用性数据,然后把数据汇报给 zabbix server,并且在一定程度上分担了zabbix se ...

  9. 细说java中的类

    前言 最近在学习<java编程思想> 学到了内部类 类不就是class吗 天天用 还能讲出花来了不成... 其实不然,在java中,类的种类和使用方式多种多样,花样繁多.其中主要有 普通类 ...

  10. cordova 5.4版本 适配全面屏 底部黑边问题

    在全面屏发布之后,Android官方提供了适配方案,即提高App所支持的最大屏幕纵横比,实现很简单,在AndroidManifest.xml中可做如下配置: 更改android.max_aspect值 ...