当前位置: 代码迷 >> MySQL >> 关于批量插入数据之小弟我见(100万级别的数据,mysql)
  详细解决方案

关于批量插入数据之小弟我见(100万级别的数据,mysql)

热度:45   发布时间:2016-05-05 16:45:07.0
关于批量插入数据之我见(100万级别的数据,mysql)

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

测试数据库为mysql!!!

方法一:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  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. ????}??

?

输出时间:cast : 23 ms

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

?

?

?

方法二:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  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. ????}??

注:注释就没有了,和上面类同,下面会有分析!

控制台输出:cast : 111 ms

执行时间是上面方法的5倍!

?

?

方法三:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  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. ????????????//?返回更新的结果集条数??
  15. ????????????public?int?getBatchSize()?{??
  16. ????????????????return?count;??
  17. ????????????}??
  18. ????????});??
  19. ????????Long?end?=?new?Date().getTime();??
  20. ????????System.out.println("cast?:?"?+?(end?-?begin)?/?1000?+?"?ms");??
  21. ????}??

该方法采用的是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中可用性还是很高的!

?

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

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

?

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案