前提:前些天接到一个同步数据需求,把Oracle里面的数据同步到MySQL数据库里面。实现同步数据必须保持两边的字段类型和字段长度一致。关于Oracle varchar2 和MySQL varchar 字段长度关系,我会在下一篇详解。同步数据是依照Oracle数据库的数据为准,所以同步过后MySQL数据库会存在一些脏数据,必须删除。但是脏数据肯定不少,这就牵扯到了MySQL的批量删除。我先把错误方法列出来,看看各位有没有踩坑。然后再推荐使用哪些方法下面列举的是使用使用JPA的形式删除:
正常逻辑是这样:JPA直接执行SQL删除,把同步过来的数据取出id存在List里面,用List避免同步过来有重复数据,
错误删除方法1:
在dao层使用JPA拼接SQL写法,下面这个方法会变为sql:
delete from User where id in();
@Transactional
void deleteUserByIdIn(List<String> ids);
这是常用的批量删除写法,把需要删除的ID塞到List集合里面,然后把集合塞给删除方法,但是调用这个写法去删除上万条数据的话就会报内存溢出这个错误。
错误方法2:
或者是使用这种方法,把装有ID的List集合通过ID查询出实体转在另一个List实体集合里面,在dao层继承了extends JpaRepository之后,调用deleteAllInBatch删除方法,删除实体是要比通过id删除要快得多。但是数据量太太还是会内存溢出
dao.deleteAllInBatch();
错误方法3:
写SQL,拼接之后然后通过JPA执行SQL,这样压力就放到数据库层面了,服务器就不会卡死,这也是错误的。数据库默认SQL最大的大小是1M,如果删除数据量大,超过了1M还是会内存溢出,虽然可以更改这个最大值,但是比较麻烦。
sql="delete from t_user where id in(?)";
String param = StringUtils.join(list, ",");--list是装有ID的集合
正确解决方法之一:
会出现上面这些报错情况是因为数据量太多了不能同时删除,那我们可以采取分页形式,不用全部展示出来,一点点的删除。
只要是通过分页删除,不管你是写SQL还是其他的基本删除方法,都可以使用。
List<List<String>> partition = Lists.partition(list, 500);
//删除
for (List<String> resultList : partition){
dao.deleteSaasBuildByIdIn(resultList);
}
以上就是MySQL批量删除数据-避免内存溢出的方法,如果你还有更好的,也希望你可以提出来,大家努力做一个高效的程序猿。对你有帮助的话可以多多关注一下。