最近好奇做了一个测试,使用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的效率最高。