MySQL批量插入操作相较于单次循环插入有较大的优势,在特定场景下,有比较重要的应用价值。
最近要实现一个批量插入数据存储到mysql数据库里的数据,但是csdn找了一下,发现暂时没找到心中想要的轮子,干脆自己写了一个,然后分享出来。
List<BasAreaDiseaselistLog> basAreaDiseaselistLogs = new ArrayList<>();
basAreaDiseaselist.forEach(diseaselistLog -> {
BasAreaDiseaselistLog basAreaDiseaselistLog = new BasAreaDiseaselistLog();
BeanUtils.copyBeanProp(basAreaDiseaselistLog,diseaselistLog);
basAreaDiseaselistLog.setSrcId(diseaselistLog.getBasAreaDiseaselistId());
basAreaDiseaselistLog.setLogTime(DateUtils.getNowDate());
basAreaDiseaselistLog.setLogerName(SecurityUtils.getUsername());
basAreaDiseaselistLog.setOprtType(Long.valueOf(oprtType));
if(diseaselistLog.getUpdateTime() != null){
basAreaDiseaselistLog.setUpdateTime(diseaselistLog.getUpdateTime());
}
if(StringUtils.isNotBlank(diseaselistLog.getUpdateBy())){
basAreaDiseaselistLog.setUpdateBy(diseaselistLog.getUpdateBy());
}
basAreaDiseaselistLogs.add(basAreaDiseaselistLog);
});
iBasAreaDiseaselistLogService.insertBasAreaDiseaselistLog(basAreaDiseaselistLogs);
public int insertBasAreaDiseaselistLog(List<BasAreaDiseaselistLog> basAreaDiseaselistLogs);
<insert id="insertBasAreaDiseaselistLog">
insert into BAS_AREA_DISEASELIST_LOG
( SRC_ID,
DISEASE_CODE,
DISEASE_NAME,
FST_SPELL,
FUL_SPELL,
DISEASE_TYPE,
MEMO,
REMARK,
CRTE_TIME,
CRTER_NAME,
UPDT_TIME,
UPDTR_NAME,
STATUS,
LOG_TIME,
LOGER_NAME,
OPRT_TYPE )
values
<foreach item="item" index="index" collection="list" separator=",">
( #{item.srcId,jdbcType=BIGINT},
#{item.diseaseCode,jdbcType=VARCHAR},
#{item.diseaseName,jdbcType=VARCHAR},
#{item.fstSpell,jdbcType=VARCHAR},
#{item.fulSpell,jdbcType=VARCHAR},
#{item.diseaseType,jdbcType=BIGINT},
#{item.memo,jdbcType=VARCHAR},
#{item.remark,jdbcType=VARCHAR},
#{item.crteTime,jdbcType=TIMESTAMP},
#{item.crterName,jdbcType=VARCHAR},
#{item.updtTime,jdbcType=TIMESTAMP},
#{item.updtrName,jdbcType=VARCHAR},
#{item.status,jdbcType=BIGINT},
#{item.logTime,jdbcType=TIMESTAMP},
#{item.logerName,jdbcType=VARCHAR},
#{item.oprtType,jdbcType=BIGINT} )
</foreach>
</insert>
批量插入效率比单次插入要高很多,能节省大约2/3的时间,原因在于:
操作的事务性。单次插入时,每个insert会开启一个事务,当执行很多insert的时候,会影响插入的性能。使用批量插入,可以在执行完成之后commit,保证了整批数据要么同时插入,要么都不插入。批量插入有数据量的限制,即max_allowed_packet值,超过最大值会报错,但是一般情况下不会超过最大值,如果需要插入几十万条甚至上百万条数据,就需要对这种情况进行处理。
(1)降低了日志(MySQL的binlog和innodb的事务日志)刷盘的数据量和频率。
(2)减少了SQL语句的解析次数。
(3)减少了网络传输的IO等。
创建表的时候,索引要选择好,本人亲测990万条数据插入一张表,表有一个datetime类型的字段索引,mysql的配置文件也可以优化一下,会大大提高插入速度。
这里对mysql批量插入进行一个小的总结,本质上是将很多条待插入的数据拼接为一条SQL语句,再执行插入操作,在Excel导入等场景下是很有用的。实际开发中,我们更加喜欢使用通过程序代码进行批量添加操作(使用事务提交,批量插入数据库),使用上述的方式在插入测试数据或者其他低要求时比较合适,速度确实快。