我喜欢有空就回头看看自己的代码,看看有没有可以优化的地方。有时顺带会看看同事写的代码,同事写的好的地方会给我带来启发,差的地方我会心里偷笑,并且注意以后不要犯这样的错误,能顺手改掉就改掉了。有一次我发现我有个同事一直都是在循环中新增数据,我感觉在循环中使用MybatisPlus新增,每次都要创建新的连接,向MySQL发送网络请求,会增加额外的开销。Mybatis中有批量新增的写法,换成批量新增一次性将数据新增进去一定会更好。
这个同事可能是为了方便,不想新写一条sql,也有可能是根本没有注意到这一点。但其实我只是从理论上想到了这一点,并没有真正地去实践过。于是我问了问ChatGPT。他给出的回复确定了我的想法是正确的:
那么,这个性能差距究竟会有多明显呢?还得是做个实验。
本次实验使用的服务器是我在腾讯云上买的1核2G服务器,仅供参考。
新建了一个User类,只有id和name两个属性。以下是核心代码:
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
private final UserMapper userMapper;
@Override
public void circulationWrite() {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (int i = 0; i < 1000; i++) {
User user = new User();
user.setName("user" + i);
userMapper.insert(user);
}
stopWatch.stop();
System.out.println(stopWatch.getTotalTimeMillis());
}
@Override
public void onceWrite() {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
List<User> userList = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
User user = new User();
user.setName("user" + i);
userList.add(user);
}
userMapper.insertUserList(userList);
stopWatch.stop();
System.out.println(stopWatch.getTotalTimeMillis());
}
}
<insert id="insertUserList">
insert into `user` (name) values
<foreach collection="userList" separator="," item="item">
(#{item.name})
</foreach>
</insert>
我分别测试了插入10,100,1000,10000条数据四种情况,结果发现每种情况都是批量插入比循环插入的效率更高。
我将新增对象数量与时间的记录做了一张excel表。从下表可见效率基本在22倍到85倍之间,两种写法的差距非常大。
因此,不论是在新增条数多还是少的情况下,都是使用Mybatis的批量新增效率更高。在少量新增(比如新增条数小于10的情况下)的时候虽然提升也挺大,但是偷个懒不写sql带来的性能差距也不是不可接受。综上所述,不要再写循环嵌套新增啦!