<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xingceng.bimsys.dao.BimModelDataDao">
<insert id="saveBatch" parameterType="java.util.List">
INSERT INTO `bimangle_data`(`entity_id`,`attribute_id`,`value_id`,`name`,`value`,`model_id`) VALUES
<foreach collection="item" separator="," item="item">
(#{item.entityId},#{item.attributeId},#{item.valueId},#{item.name},#{item.value},#{item.modelId})
</foreach>
</insert>
使用MyBatis 原生批量插入时,当传入的LIst数据量过大就会出现以下错误
这是因为使用 MyBatis 原生批量插入拼接的插入 SQL 大小是 4.56M,而默认情况下 MySQL 可以执行的最大 SQL 为 4M,那么在程序执行时就会报错了。
解决方案:
将LIst分成多份循环插入,也就是分片批量插入
第一步:我们先要添加 Guava 框架的支持,在 pom.xml 中添加以下引用:
<!-- google guava 工具类 -->
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
第二部:改造我们的 MyBatis 批量插入代码
long stime = System.currentTimeMillis(); // 统计开始时间
System.out.println("一共插入"+bimangleDataList.size()+"条数据");
// 分片批量插入
// 分为 n 份,每份 1000 条
List<List<BimangleData>> listPartition = Lists.partition(bimangleDataList, 1000);
// 分片批量插入
for (List<BimangleData> item : listPartition) {
bimModelDataDao.saveBatch(item);
}
long etime = System.currentTimeMillis(); // 统计结束时间
System.out.println("执行时间:" + (etime - stime));
读取三个不同大小的模型算量测试
27152 1.7秒
72561 4秒
322830 18秒
最终结果
一次插入32w算量数据从90分钟优化成18秒