首页 技术 正文
技术 2022年11月19日
0 收藏 590 点赞 3,865 浏览 4659 个字

因前段时间去面试,问到如何高效向数据库插入10万条记录,之前没处理过类似问题,也没看过相关资料,结果没答上来,今天就查了些资料,总结出三种方法:

测试数据库为MySQL!!!

方法一:

  1. public static void insert() {
  2. // 开时时间
  3. Long begin = new Date().getTime();
  4. // sql前缀
  5. String prefix = “INSERT INTO tb_big_data (count, create_time, random) VALUES “;
  6. try {
  7. // 保存sql后缀
  8. StringBuffer suffix = new StringBuffer();
  9. // 设置事务为非自动提交
  10. conn.setAutoCommit(false);
  11. // Statement st = conn.createStatement();
  12. // 比起st,pst会更好些
  13. PreparedStatement pst = conn.prepareStatement(“”);
  14. // 外层循环,总提交事务次数
  15. for (int i = 1; i <= 100; i++) {
  16. // 第次提交步长
  17. for (int j = 1; j <= 10000; j++) {
  18. // 构建sql后缀
  19. suffix.append(“(” + j * i + “, SYSDATE(), ” + i * j
  20. * Math.random() + “),”);
  21. }
  22. // 构建完整sql
  23. String sql = prefix + suffix.substring(0, suffix.length() – 1);
  24. // 添加执行sql
  25. pst.addBatch(sql);
  26. // 执行操作
  27. pst.executeBatch();
  28. // 提交事务
  29. conn.commit();
  30. // 清空上一次添加的数据
  31. suffix = new StringBuffer();
  32. }
  33. // 头等连接
  34. pst.close();
  35. conn.close();
  36. } catch (SQLException e) {
  37. e.printStackTrace();
  38. }
  39. // 结束时间
  40. Long end = new Date().getTime();
  41. // 耗时
  42. System.out.println(“cast : ” + (end – begin) / 1000 + ” ms”);
  43. }
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

该方法目前测试是效率最高的方法!

方法二:

  1. public static void insertRelease() {
  2. Long begin = new Date().getTime();
  3. String sql = “INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)”;
  4. try {
  5. conn.setAutoCommit(false);
  6. PreparedStatement pst = conn.prepareStatement(sql);
  7. for (int i = 1; i <= 100; i++) {
  8. for (int k = 1; k <= 10000; k++) {
  9. pst.setLong(1, k * i);
  10. pst.setLong(2, k * i);
  11. pst.addBatch();
  12. }
  13. pst.executeBatch();
  14. conn.commit();
  15. }
  16. pst.close();
  17. conn.close();
  18. } catch (SQLException e) {
  19. e.printStackTrace();
  20. }
  21. Long end = new Date().getTime();
  22. System.out.println(“cast : ” + (end – begin) / 1000 + ” ms”);
  23. }
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倍!

方法三:

  1. public static void insertBigData(SpringBatchHandler sbh) {
  2. Long begin = new Date().getTime();
  3. JdbcTemplate jdbcTemplate = sbh.getJdbcTemplate();
  4. final int count = 10000;
  5. String sql = “INSERT INTO tb_big_data (count, create_time, random) VALUES (?, SYSDATE(), ?)”;
  6. jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
  7. // 为prepared statement设置参数。这个方法将在整个过程中被调用的次数
  8. public void setValues(PreparedStatement pst, int i)
  9. throws SQLException {
  10. pst.setLong(1, i);
  11. pst.setInt(2, i);
  12. }
  13. // 返回更新的结果集条数
  14. public int getBatchSize() {
  15. return count;
  16. }
  17. });
  18. Long end = new Date().getTime();
  19. System.out.println(“cast : ” + (end – begin) / 1000 + ” ms”);
  20. }
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中可用性还是很高的!

刚才开始研究大数据方面的问题,以上也只是真实测试的结果,并不一定就是事实,有好的建议,大家请指正,谢谢!

相互学习,才能进步更快!

晚点会把源码发上来,大家可以直接去下载测试!

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,075
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,551
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,399
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,176
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,811
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,893