© 版权声明:本文为博主原创文章,转载请注明出处

最近同事碰到大批量数据导入问题,因此也关注了一下。大批量数据导入主要存在两点问题:内存溢出和导入速率慢。

内存溢出:将文件中的数据全部取出放在集合中,当数据过多时就出现Java内存溢出,此时可通过调大JVM的最大可用内存(Xmx)解决,

        但终究不是王道。

        MySQL支持一条SQL语句插入多条记录的操作,并且效率比单条插入快的不是一点点;但是MySQL一次可接受的数据包大小

        也是有限制的,当一次插入过多时也可能造成数据包内存溢出,此时可通过调大MySQL的max_allowed_packet 解决,

        但也不是王道。

导入速率慢:单条插入就不用考虑了,因此考虑一条SQL语句插入多条记录,

        根据上述所说还应控制好一条插入的数据大小不能超过max_allowed_packet 的配置。

下面比较了用PreparedStatement和直接拼接SQL两种批量插入的方式的速率(一次插入1w条)

package org.javaio.CSV;import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Date;import com.mysql.jdbc.Connection;/*** 导入大批量CSV文件**/
public class Test {/*** jdbc所属,暂不使用*/private final static String url = "jdbc:mysql://localhost:3306/demo_test?useSSL=true&characterEncoding=utf8";private final static String name = "root";private final static String pwd = "20121221";private static Connection conn;private static PreparedStatement ps;/*** 解析csv文件并插入到数据库中,暂不使用(jdbc)* * @param args* * @throws Exception*/public static void main(String[] args) throws Exception {Test test = new Test();// psBatch 时间统计 - 开始SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String startTime = sdf.format(new Date());System.out.println("psBatch 开始时间为:" + startTime);System.out.println("psBatch 开始执行...");// 使用PreparedStatement批量插入int idx = test.psBatch();// 统计时间 - 结束System.out.println("psBatch 执行完成,共插入" + idx + "条数据");String endTime = sdf.format(new Date());System.out.println("psBatch 结束时间为:" + endTime);System.out.println();// 时间统计 - 开始startTime = sdf.format(new Date());System.out.println("sqlBatch 开始时间为:" + startTime);System.out.println("sqlBatch 开始执行...");// 使用SQL语句批量插入idx = test.sqlBatch();// 统计时间 - 结束System.out.println("sqlBatch 执行完成,共插入" + idx + "条数据");endTime = sdf.format(new Date());System.out.println("sqlBatch 结束时间为:" + endTime);}/*** 使用PreparedStatement批量插入* * @return* * @throws Exception*/private int psBatch() throws Exception {int idx = 0;// 行数try {// 读取CSV文件FileInputStream fis = new FileInputStream("C:/Users/chen/Desktop/data/ceshi .csv");InputStreamReader isr = new InputStreamReader(fis, "UTF-8");BufferedReader br = new BufferedReader(isr);String line;// 行数据String[] column = new String[4];// 列数据// 获取数据库连接conn = getConnection();// 设置不自动提交conn.setAutoCommit(false);// SQLString sql = "insert into test (name, `desc`, column1, column2, column3, column4) "+ "values (?, ?, ?, ?, ?, ?)";ps = conn.prepareStatement(sql);while ((line = br.readLine()) != null) {// 循环读取每一行idx++;// 计数column = line.split(",");ps.setString(1, column[0]);  if (column.length >= 2 && column[1] != null) {ps.setString(2, column[1]);} else {ps.setString(2, "");}if (column.length >= 3 && column[2] != null) {ps.setString(3, column[2]);} else {ps.setString(3, "");}if (column.length >= 4 && column[3] != null) {ps.setString(4, column[3]);} else {ps.setString(4, "");}ps.setString(5, "type");ps.setString(6, "1");ps.addBatch();if (idx % 10000 == 0) {ps.executeBatch();conn.commit();ps.clearBatch();}}if (idx % 10000 != 0) {ps.executeBatch();conn.commit();ps.clearBatch();}} catch (Exception e) {System.out.println("第" + idx + "前一万条数据插入出错...");} finally {try {if (ps != null) {// 关闭连接ps.close();}if (conn != null) {conn.close();}} catch (Exception e2) {e2.printStackTrace();}}return idx;}/*** 使用sql语句批量插入* * @return* * @throws Exception*/private int sqlBatch() {int idx = 0;// 行数try {// 读取CSV文件FileInputStream fis = new FileInputStream("C:/Users/chen/Desktop/data/ceshi .csv");InputStreamReader isr = new InputStreamReader(fis, "UTF-8");BufferedReader br = new BufferedReader(isr);String line;// 行数据String[] column = new String[4];// 列数据// 获取数据库连接conn = getConnection();// SQLStringBuffer sql = new StringBuffer("insert into test (name, `desc`, column1, column2, column3, column4) "+ "values ");while ((line = br.readLine()) != null) {// 循环读取每一行idx++;// 计数column = line.split(",");sql.append("('" + column[0] + "', '");if (column.length >= 2 && column[1] != null) {sql.append(column[1] + "', '");} else {sql.append("', '");}if (column.length >= 3 && column[2] != null) {sql.append(column[2] + "', '");} else {sql.append("', '");}if (column.length >= 4 && column[3] != null) {sql.append(column[3] + "', '");} else {sql.append("', '");}sql.append("type', '1'),");if (idx % 10000 == 0) {String executeSql = sql.toString().substring(0, sql.toString().lastIndexOf(","));ps = conn.prepareStatement(executeSql);ps.executeUpdate();sql = new StringBuffer("insert into test (name, `desc`, column1, column2, column3, column4) "+ "values ");}}if (idx % 10000 != 0) {String executeSql = sql.toString().substring(0, sql.toString().lastIndexOf(","));ps = conn.prepareStatement(executeSql);ps.executeUpdate();}} catch (Exception e) {System.out.println("第" + idx + "前一万条数据插入出错...");} finally {try {if (ps != null) {// 关闭连接ps.close();}if (conn != null) {conn.close();}} catch (Exception e2) {e2.printStackTrace();}}return idx;}/*** 获取数据库连接* * @param sql*                SQL语句*/private Connection getConnection() throws Exception {Class.forName("com.mysql.jdbc.Driver");conn = (Connection) DriverManager.getConnection(url, name, pwd);return conn;}}

速率比较:为了排除其他影响,两次次都是在空表的情况下进行导入的

  用SQL拼接批量插入用时大概3-4分钟

  用PreparedStatement批量插入用时大概10分钟

转载于:https://www.cnblogs.com/jinjiyese153/p/7382345.html

java大批量数据导入(MySQL)相关推荐

  1. 关于使用mybatis-plus进行大批量数据导入

    一.背景 项目中经常会遇到需要对数据库进行大批量数据导入的问题,就目前java应用常用的springboot+mybatis-plus架构而言,在大批量数据导入时不是很清晰,本文做简单分析及解决,希望 ...

  2. 使用MapReduce将HDFS数据导入Mysql

    使用MapReduce将Mysql数据导入HDFS代码链接 将HDFS数据导入Mysql,代码示例 package com.zhen.mysqlToHDFS;import java.io.DataIn ...

  3. 将Excel数据导入mysql数据库的几种方法

    将Excel数据导入mysql数据库的几种方法 "我的面试感悟"有奖征文大赛结果揭晓! 前几天需要将Excel表格中的数据导入到mysql数据库中,在网上查了半天,研究了半天,总结 ...

  4. mysql两条记录合成一条数据_踩坑记录之csv数据导入MySQL

    可能采坑的操作 将excel表格转换成csv 逗号分隔,然后notepad检查文件是否是utf8编码,保存. 打开 phpMyAdmin , 选择要导入的表格,然后点击导入: 导入设置 点击执行之后, ...

  5. Shell_mysql命令以及将数据导入Mysql数据库

    连接MYSQL数据库 mysql -h${db_ip} -u${db_user} -p${db_pawd} -P${db_port} -D${db_name} -s -e "${sql}&q ...

  6. mysql rrd_将RRD数据库中数据导入MYSQL中

    一.RRD数据库及RRDTOOL简介 意为Round Robin Database.设计理念为按照round-robin的方式进行存储,在一个周期之后(可自己定义),新的数据会覆盖掉原来的数据.所以R ...

  7. cpp导入excel到mysql_将EXCEL表格中的数据导入mysql数据库表中

    本文转载自http://blog.sina.com.cn/s/blog_5d972ae00100gjij.html 今天项目上遇到需要将excel中的数据导入到数据库的classify表中,于是乎拼命 ...

  8. 维基百科 mysql_把维基百科首页词条的数据导入mysql【Python】

    title: 把维基百科首页词条的数据导入mysql[Python] date: 2016-09-13 0:59:28 tags: 1.此文是跟着上一篇来写的,之前,已经完成了对维基百科词条的数据采集 ...

  9. navcat导入mysql bak_navcat excel数据导入mysql的方法

    navcat excel数据导入mysql的方法 先navcat导出 xls格式 然后把数据复制到往这个xls里 (按照这个xls格式) 然后导入mysql就行了 如果导入的过程无法识别excel里的 ...

最新文章

  1. 经典PV操作问题 [转]
  2. 动作分析 姿态估计_关于大片人物特效少不了的人体姿态估计,这里有一份综述文章...
  3. 一段javascript告警回放代码
  4. shell数组中“和@的妙用
  5. 5848. 树上的操作
  6. java 牛生小牛_例题:大牛生小牛的问题解决方法
  7. 为什么Docker容器将占领世界
  8. mysql 恢复root权限_Linux MySQL root权限恢复[图文]
  9. bzoj 1433: [ZJOI2009]假期的宿舍
  10. python自动搜索最佳超参数之GridSearchCV函数
  11. 华为 项目管理10大模板 【Word版 (可直接套用)】
  12. Oracle数据恢复工具-ODU破解记录
  13. 撩妹代码html,Web前端
  14. Mendeley中WordPlugin问题
  15. 考研英语单词-近义词分类-Fifth Day
  16. 未来5年做好随时失业的准备
  17. python中的_和__
  18. WHALE 会员指南(第 1 部分)
  19. Java标准简历制作
  20. 2020笔记本性价比之王_【笔记本电脑选购】2020年有哪些款高性价比笔记本电脑值得推荐?(十一月更新)...

热门文章

  1. centos6配置mysql远程访问_mysql设置密码远程访问编码格式
  2. Java LinkedHashMap 逆序遍历
  3. 注解@Mapper、@MapperScan
  4. 前端面试准备---浏览器和网络篇(一)
  5. 人工智能为失散家人寻找“回家路”
  6. TypeScript 3.3发布:改进了联合类型调用和构建时间
  7. spring aop获取目标对象的方法对象(包括方法上的注解)(转)
  8. Gradle2.0用户指南翻译——第二章. 概述
  9. Android开发之Canvas rotate方法释疑
  10. SIP(Session Initiation Protocol,会话初始协议)