今天在写mybatis批量加入时,发现插入时间太长了,才几千条数据就要接近一分钟才能完成,所以也去网上找了下解决方案
一、一条一条插入
<insert id="insert" parameterType="com.cntd.entity.Attack">
insert into attack (id,score, container)
values
( #{id,jdbcType=INTEGER},
#{score,jdbcType=TINYINT},
#{container,jdbcType=LONGVARCHAR})
</insert>
//这种插入效率太慢了 每一次都要执行一次sql插入语句
List<Attack> list = .....
for(Attack attack: list){
attackMapper.insert(attack);
}
二、去网上查找了对应的解决方案
大概就是xml使用 foreach 来达到一条插入语句插入n条内容。
大概有两种情况
一种解读之后发现也是一样一条一条插入那和我刚刚开始的情况是一样的,使用以下动态sql的情况
<insert id="insertBatch" parameterType="List" useGeneratedKeys="true" keyProperty="id">
<foreach collection="list" item="item" index="index" separator=";">
insert into cntd_attack
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="score != null">
score,
</if>
<if test="container != null">
container,
</if> values
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="score != null">
#{score,jdbcType=TINYINT},
</if>
<if test="container != null">
#{container,jdbcType=LONGVARCHAR},
</if>
</foreach>
</insert>
三、最终解决方案
只使用foreach,这样就能达到我们一次性插入多条数据的情况了。
但是一次性插入不要太多,mysql默认一次性最大插入1MB的数据,如果超过这个数据量将会报错, 最后我选择了一次性插入1000条数据,速度果然杠杠上升。
<insert id="insertBatch" parameterType="List" useGeneratedKeys="true" keyProperty="id">
insert into cntd_attack
(score, container)
values
<foreach collection="list" item="item" index="index" separator=",">
(
#{item.score,jdbcType=TINYINT},
#{item.container,jdbcType=LONGVARCHAR}
)
</foreach>
</insert>