一、一次性直接梭哈
springboot项目直接一次性批量插入30万条,代码如下:
@Test
public void testBatchInsertUser() {
System.out.println("===== 开始插入数据 =====");
long startTime = System.currentTimeMillis();
List<User> userList = new ArrayList<>();
for (int i = 1; i <= 300000; i++) {
User user = new User();
user.setId(i);
user.setUsername("共饮一杯无 " + i);
user.setAge((int) (Math.random() * 100));
userList.add(user);
}
// 最后插入剩余的数据
userMapper.batchInsertUser(userList);
long spendTime = System.currentTimeMillis()-startTime;
System.out.println("成功插入 30 万条数据,耗时:"+spendTime+"毫秒");
}
控制台输出:
Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (27759038 >yun 4194304). You can change this value on the server by setting the max_allowed_packet’ variable.
超出最大数据包限制了,可以通过调整
max_allowed_packet
限制来提高可以传输的内容,不过由于30万条数据超出太多,这个不可取,梭哈看来是不行了 😅😅😅
既然梭哈不行那我们就一条一条循环着插入行不行呢
二、循环逐条插入
调整执行代码如下:
@Test
public void testCirculateInsertUser() {
System.out.println("===== 开始插入数据 =====");
long startTime = System.currentTimeMillis();
for (int i = 1; i <= 300000; i++) {
User user = new User();
user.setId(i);
user.setUsername("共饮一杯无 " + i);
user.setAge((int) (Math.random() * 100));
// 一条一条新增
userMapper.insertUser(user);
System.out.println("user = " + user);
}
long spendTime = System.currentTimeMillis()-startTime;
System.out.println("成功插入 30 万条数据,耗时:"+spendTime+"毫秒");
}
执行后可以发现磁盘IO占比飙升,一直处于高位。
一直在执行
总共执行了14909367毫秒,换算出来是4小时八分钟。太慢了。。
三、使用MyBatis特性每1000条进行插入一次
使用了 MyBatis 的批处理操作,将每 1000 条数据放在一个批次中插入,能够较为有效地提高插入速度。同时请注意在循环插入时要带有合适的等待时间和批处理大小,以防止出现内存占用过高等问题。此外,还需要在配置文件中设置合理的连接池和数据库的参数,以获得更好的性能。
代码实现:
/**
* 分批次批量插入
* @throws
*/
@Test
public void testBatchInsertUserLs() {
System.out.println("===== 开始插入数据 =====");
long startTime = System.currentTimeMillis();
try {
List<User> userList = new ArrayList<>();
for (int i = 1; i <= 300000; i++) {
User user = new User();
user.setId(i);
user.setUsername("共饮一杯无 " + i);
user.setAge((int) (Math.random() * 100));
userList.add(user);
if (i % 1000 == 0) {
userMapper.batchInsertUser(userList);
// 每 1000 条数据提交一次事务
userList.clear();
}
}
// 最后插入剩余的数据
if(!StringUtils.isEmpty(userList)) {
userMapper.batchInsertUser(userList);
}
long spendTime = System.currentTimeMillis()-startTime;
System.out.println("成功插入 30 万条数据,耗时:"+spendTime+"毫秒");
} catch (Exception e) {
e.printStackTrace();
}
}
结果11秒可以完成数据插入操作: