前言
数据库使用的mysql,jdk版本1.8,springboot环境, 需要注意的是我们测试的单条sql比较短
max_allowed_packet指代mysql服务器端和客户端在一次传送数据包的过程当中最大允许的数据包大小。这里是4M
对比以下三种方式:
- for循环执行单条插入语句
- xml拼接sql
- 批处理执行
代码
mapper
@Mapper
public interface UserMapper {
int insert(User user);
int insertByBatch(List<User> users);
int delete();
}
xml
<insert id="insert" parameterType="com.example.mybatisdemo.entity.User">
insert into user (name,age) values(#{name},#{age});
</insert>
<insert id="insertByBatch" parameterType="java.util.List">
insert into user (name,age) values
<foreach collection="list" item="item" separator=",">
(#{item.name},#{item.age})
</foreach>
</insert>
<delete id="delete">
delete from user
</delete>
拼接方式需要注意如果使用的是Oracle
<foreach collection="list" item="item" separator ="UNION ALL">
</foreach>
测试类
@SpringBootTest
class MybatisdemoApplicationTests {
@Autowired
UserMapper userMapper;
@Autowired
SqlSessionFactory sqlSessionFactory;
private List<User> users = new ArrayList<User>();
@Test
void delete(){
userMapper.delete();
}
@Test
void insert() {
for (int i = 0; i < 1000; i++){
User user = new User();
user.setName("人物"+i);
user.setAge(i);
users.add(user);
}
long start = System.currentTimeMillis();
users.forEach(userMapper::insert);
System.out.println(System.currentTimeMillis() - start);
}
@Test
void insertByBatch(){
for (int i = 0; i < 1000; i++){
User user = new User();
user.setName("人物"+i);
user.setAge(i);
users.add(user);
}
long start = System.currentTimeMillis();
userMapper.insertByBatch(users);
System.out.println(System.currentTimeMillis() - start);
}
@Test
void insertByOnce(){
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
long start = 0L;
for (int i = 0; i < 1000; i++){
User user = new User();
user.setName("人物"+i);
user.setAge(i);
start = System.currentTimeMillis();
mapper.insert(user);
if (i%1000 == 999){
//每1000条提交一次防止内存溢出
sqlSession.commit();
sqlSession.clearCache();
}
}
// sqlSession.commit();
// sqlSession.clearCache();
System.out.println(System.currentTimeMillis() - start);
}
}
对比
方式 | 50条 | 1000条 | 2000条 | 3000条 |
for循环 | 562ms | 2577ms | 4828ms | 6144ms |
xml拼接 | 479ms | 582ms | 618ms | 655ms |
批处理 | 75ms | 1683ms | 1790ms | 1843ms |
注意我们这里测试的单条sql较短,当xml拼接过长就会报以下错误
总结
循环插入单条数据 效率确实不好,但是代码量少,在需求插入数据量不大的情况也是可以使用的。
xml拼接sql方式 网上千篇一律的说任何时候都不要使用,但是我觉得在可控范围内,效率这么好为什么不使用呢,当然必须要注意上面报错的情况,还是根据实际情况而定。
批处理执行 有大量数据插入时推荐此方式。