最近好奇做了一个测试,使用spring + mybatis 对mysql插入百条数据。
第一种,通过调用service一条一条插入,出错没有回滚。
结果耗时非常长,这也是很正常的。
第二种,在100w条sql跑在同一个事物中,好处就是这一百万条数据是原子性的。统一成功或者失败。
数据生成代码
List<Log> logs = new ArrayList<Log>(100_0000); for (int i = 0; i < 100_0000; i++) { Log log = new Log(); log.setAddress(Math.random()+""); log.setJingdu(Math.random()*100); log.setWeidu(Math.random()*100); log.setTokenId(UUID.randomUUID().toString().split("-")[0]); log.setSignDate(new Date()); logs.add(log); }
批量插入代码
public void insert(Iterable<Log> logs) { for (Log l : logs) { baseDao.insert(l); } }
结果:百万次,十次测试[679, 703, 620, 564, 698, 700, 678, 686, 711, 619]单位秒
第三种 拼接sql. insert into … values (…),(…),(….)
这种方式直接卡死。
第四种 batch update
@Override public void addBatch(final List<Log> item) { String sql = "insert into log (id, token_id, sign_date,jingdu, weidu, address)values (null,?,?,?,?, ?)"; JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { // 为prepared statement设置参数。这个方法将在整个过程中被调用的次数 public void setValues(PreparedStatement pst, int i) throws SQLException { Log log = item.get(i); pst.setString(1, log.getTokenId()); pst.setDate(2,new java.sql.Date(log.getSignDate().getTime()) ); pst.setDouble(3, log.getJingdu()); pst.setDouble(4, log.getWeidu()); pst.setString(5, log.getAddress()); } // 返回更新的结果集条数 public int getBatchSize() { return item.size(); } }); }
结果[211, 216, 243, 234, 235, 238, 237, 224, 222, 226]秒
目前来看还是batchUpdate的效率最高。