关于批量插入数据之我见(100万级别的数据,mysql) (转)
因前段时间去面试,问到如何高效向数据库插入10万条记录,之前没处理过类似问题,也没看过相关资料,结果没答上来,今天就查了些资料,总结出三种方法:
方法一:
- public static void insert() {
- // 开时时间
- Long begin = new Date().getTime();
- // sql前缀
- String prefix = "INSERT INTO tb_big_data (count, create_time, random) VALUES ";
- try {
- // 保存sql后缀
- StringBuffer suffix = new StringBuffer();
- // 设置事务为非自动提交
- conn.setAutoCommit(false);
- // Statement st = conn.createStatement();
- // 比起st,pst会更好些
- PreparedStatement pst = conn.prepareStatement("");
- // 外层循环,总提交事务次数
- for (int i = 1; i <= 100; i++) {
- // 第次提交步长
- for (int j = 1; j <= 10000; j++) {
- // 构建sql后缀
- suffix.append("(" + j * i + ", SYSDATE(), " + i * j
- * Math.random() + "),");
- }
- // 构建完整sql
- String sql = prefix + suffix.substring(0, suffix.length() - 1);
- // 添加执行sql
- pst.addBatch(sql);
- // 执行操作
- pst.executeBatch();
- // 提交事务
- conn.commit();
- // 清空上一次添加的数据
- suffix = new StringBuffer();
- }
- // 头等连接
- pst.close();
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- // 结束时间
- Long end = new Date().getTime();
- // 耗时
- System.out.println("cast : " + (end - begin) / 1000 + " ms");
- }
public static void insert() {
// 开时时间
Long begin = new Date().getTime();
// sql前缀
String prefix = "INSERT INTO tb_big_data (count, create_time, random) VALUES ";
try {
// 保存sql后缀
StringBuffer suffix = new StringBuffer();
// 设置事务为非自动提交
conn.setAutoCommit(false);
// Statement st = conn.createStatement();
// 比起st,pst会更好些
PreparedStatement pst = conn.prepareStatement("");
// 外层循环,总提交事务次数
for (int i = 1; i <= 100; i++) {
// 第次提交步长
for (int j = 1; j <= 10000; j++) {
// 构建sql后缀
suffix.append("(" + j * i + ", SYSDATE(), " + i * j
* Math.random() + "),");
}
// 构建完整sql
String sql = prefix + suffix.substring(0, suffix.length() - 1);
// 添加执行sql
pst.addBatch(sql);
// 执行操作
pst.executeBatch();
// 提交事务
conn.commit();
// 清空上一次添加的数据
suffix = new StringBuffer();
}
// 头等连接
pst.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
// 结束时间
Long end = new Date().getTime();
// 耗时
System.out.println("cast : " + (end - begin) / 1000 + " ms");
}
输出时间:cast : 23 ms
该方法目前测试是效率最高的方法!
方法二:
- public static void insertRelease() {
- Long begin = new Date().getTime();
- String sql = "INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)";
- try {
- conn.setAutoCommit(false);
- PreparedStatement pst = conn.prepareStatement(sql);
- for (int i = 1; i <= 100; i++) {
- for (int k = 1; k <= 10000; k++) {
- pst.setLong(1, k * i);
- pst.setLong(2, k * i);
- pst.addBatch();
- }
- pst.executeBatch();
- conn.commit();
- }
- pst.close();
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- Long end = new Date().getTime();
- System.out.println("cast : " + (end - begin) / 1000 + " ms");
- }
public static void insertRelease() {
Long begin = new Date().getTime();
String sql = "INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)";
try {
conn.setAutoCommit(false);
PreparedStatement pst = conn.prepareStatement(sql);
for (int i = 1; i <= 100; i++) {
for (int k = 1; k <= 10000; k++) {
pst.setLong(1, k * i);
pst.setLong(2, k * i);
pst.addBatch();
}
pst.executeBatch();
conn.commit();
}
pst.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
Long end = new Date().getTime();
System.out.println("cast : " + (end - begin) / 1000 + " ms");
}
注:注释就没有了,和上面类同,下面会有分析!
控制台输出:cast : 111 ms
执行时间是上面方法的5倍!
方法三:
- public static void insertBigData(SpringBatchHandler sbh) {
- Long begin = new Date().getTime();
- JdbcTemplate jdbcTemplate = sbh.getJdbcTemplate();
- final int count = 10000;
- String sql = "INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)";
- jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
- // 为prepared statement设置参数。这个方法将在整个过程中被调用的次数
- public void setValues(PreparedStatement pst, int i)
- throws SQLException {
- pst.setLong(1, i);
- pst.setInt(2, i);
- }
- // 返回更新的结果集条数
- public int getBatchSize() {
- return count;
- }
- });
- Long end = new Date().getTime();
- System.out.println("cast : " + (end - begin) / 1000 + " ms");
- }
public static void insertBigData(SpringBatchHandler sbh) {
Long begin = new Date().getTime();
JdbcTemplate jdbcTemplate = sbh.getJdbcTemplate();
final int count = 10000;
String sql = "INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)";
jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
// 为prepared statement设置参数。这个方法将在整个过程中被调用的次数
public void setValues(PreparedStatement pst, int i)
throws SQLException {
pst.setLong(1, i);
pst.setInt(2, i);
}
// 返回更新的结果集条数
public int getBatchSize() {
return count;
}
});
Long end = new Date().getTime();
System.out.println("cast : " + (end - begin) / 1000 + " ms");
}</pre><br>
该方法采用的是spring batchUpdate执行,因效率问题,数据量只有1万条!
执行时间:cast : 387 ms
总结:方法一和方法二很类同,唯一不同的是方法一采用的是“insert into tb (...) values(...),(...)...;”的方式执行插入操作,
方法二则是“insert into tb (...) values (...);insert into tb (...) values (...);...”的方式,要不是测试,我也不知道两者差别是如此之大!
当然,这个只是目前的测试,具体执行时间和步长也有很大关系!如过把步长改为100,可能方法就要几分钟了吧,这个可以自己测试哈。。。
方法三网上很推崇,不过,效率大家也都看到了,1万条记录,耗时6分钟,可见其效率并不理想!而且方法三需要配置spring applicationContext环境才能应用!
不过,方法三在ssh/spring-mvc中可用性还是很高的!
刚才开始研究大数据方面的问题,以上也只是真实测试的结果,并不一定就是事实,有好的建议,大家请指正,谢谢!
相互学习,才能进步更快!
晚点会把源码发上来,大家可以直接去下载测试!
关于批量插入数据之我见(100万级别的数据,mysql) (转)的更多相关文章
- Mysql数据库实践操作之————批量插入数据(100万级别的数据)
第一种方法:使用insert into 插入 从Redis每次获取100条数据,根据条件去插入到Mysql数据库中: 条件: 如果当前队列中的值大于1000条,则会自动的条用该方法,该方法每次获取从队 ...
- 关于批量插入数据之我见(100万级别的数据,mysql)
因前段时间去面试,问到怎样高效向数据库插入10万条记录,之前没处理过类似问题.也没看过相关资料,结果没答上来,今天就查了些资料.总结出三种方法: 測试数据库为mysql!!! 方法一: public ...
- 如何通过Dataphin构建数据中台新增100万用户?
欢迎来到数据中台小讲堂!这一期我们来看看,作为阿里巴巴数据中台(OneData - OneModel.OneID.OneService)方法论的产品载体,Dataphin如何帮助传统零售企业实现数字化 ...
- 极限挑战—C#+ODP 100万条数据导入Oracle数据库仅用不到1秒
链接地址:http://www.cnblogs.com/armyfai/p/4646213.html 要:在这里我们将看到的是C#中利用ODP实现在Oracle数据库中瞬间导入百万级数据,这对快速批量 ...
- 多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中【我】
多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中 package com.xxx.xx.reve.service; import java.util.ArrayL ...
- .Net中DataAdapter批量插入和更新数据总结
前言 前段时间一直在忙着项目上线,在做项目的同时遇到了一些之前不曾碰到的问题,因为没有经验,只能从网上找一些相关的解决方案,但是网上提供的资料实在是太杂,有的根本不能用,耗时又耗力. 我希望把我这段时 ...
- Hibernate 数据的批量插入、更新和删除
4.2 Hibernate的批量处理 Hibernate完全以面向对象的方式来操作数据库,当程序里以面向对象的方式操作持久化对象时,将被自动转换为对数据库的操作.例如调用Session的delete ...
- 利用pipeline批量插入数据到redis
在推荐系统中,推荐候选集格式一般是,itemid itemid_list.要把itemid作为key,推荐列表作为value批量插入到redis. 比如文件cf.data为: cf_763500210 ...
- MySQL on duplicate key update 批量插入并更新已存在数据
业务上经常存在一种现象,需要批量往表中插入多条数据,但在执行过程中,很可能因为唯一键冲突,而导致批量插入失败.因此需要事先判断哪些数据是重复的,哪些是新增的.比较常用的处理方法就是找出已存在的数据,并 ...
随机推荐
- POJ 3398 Perfect Service(树型动态规划,最小支配集)
POJ 3398 Perfect Service(树型动态规划,最小支配集) Description A network is composed of N computers connected by ...
- 小哈学Python第三课-字符集编码
table.hovertable { font-family: verdana, arial, sans-serif; font-size: 11px; color: #333333; border- ...
- 操作系统,银行家算法模拟实现(Windows 环境 C++)
计算机操作系统课设需要,写了两个下午的银行家算法(陷在bug里出不来耽误了很多时间),参考计算机操作系统(汤子瀛) 实现过程中不涉及难度较大的算法,仅根据银行家算法的思想和步骤进行实现.以下为详细步骤 ...
- 文本处理常用命令--sort,uniq,cut,wc
#文本处理命令--sort,cut,wc及其他 文本处理命令还有其他常用的,比如:sort,cut,wc 1.cut命令的用法 cut命令: cut - remove sections from ea ...
- [肯定不知道]PeopleSoft中PSADMIN你不知道的秘密
PeopleSoft psadmin工具是用于管理PS App server,process scheduler 和 web server节点的.可以使用一些设置菜单选项来管理或配置上面提到的任何组件 ...
- (转)每天一个linux命令(27):linux chmod命令
场景:在项目部署过程中经常需要给不同目录授权! 1 简介 chmod命令用于改变linux系统文件或目录的访问权限.用它控制文件或目录的访问权限.该命令有两种用法.一种是包含字母和操作符表达式的文字设 ...
- Objective-C MapKit的使用-LBS简单的租车主界面demo
效果 分析 三个view:地图view.车辆信息view.车辆类型选择view 地图view:大头针的摆放,根据不同的种类显示大头针 车辆信息view:根据当前点击的大头针显示对应的车辆信息 车辆类型 ...
- 【JAVASCRIPT】React学习-巧用 props 的 children 属性实现内容填充
背景 平常写组件,经常遇到需要获取内容放入组件内部的情形. 实现方法 我们有两种实现方式 1. 自定义 props render 的时候通过获取 this.props.content 填充到组件内部 ...
- python有三种导入模块的方法(转)
原文:http://www.cnblogs.com/allenblogs/archive/2011/11/15/2055149.html python有三种导入模块的方法 其一, import mod ...
- Linux 服务器如何配置网站以及绑定域名
因为域名没有备案,国内地区不能直接域名访问.前段时间在阿里云租购了一台的香港服务器,添加子域名时解析的时发现不能添加直接解析至端口,找了些资料,发现了Nginx绑定域名的方法,在这里做个记录. 1.香 ...