背景
需要每天删除过期的数据。例如其中一个表是8亿行,400gb左右,一共是4天的数据。每天会有一天的数据过期,并且有新一天的数据进入。即每天需要删除2亿行左右。时间分区字段years_per_slice有单独索引。
简单的总结需求:删除某一天的数据。
使用的删除方案是
delete from table_test where years_per_slice='2018-09-12' limit 1000
遇到的问题
主要有两个问题:1、删除速度慢,所有表加起来要八小时左右;2、每次删除遇到了慢查询。
解决方案
网上资料
网上提到了一些解决方案,避免了删除导致锁表影响查询的问题,这些方案解决的问题不是我的问题。
也有一些使用新表存储有用数据然后删除旧表的方案,可以部分满足我的需求。但是我的部分表存储几十天数据,但是需要废除一天的数据,这种方案不适合,因为要保留的数据比要删除的更多。
自己的解决方案
原因分析
- 虽然时间分区有索引,且起作用了,但是使用
delete from table_test where years_per_slice='2018-09-12' limit 1000
的时候,是先根据years_per_slice做排序,然后取出前1000条。这个排序就会导致执行超时。
解决方案
1、先去查询需要删除的id:
select id from table_test where years_per_slice='2018-09-12' limit 1;
因为id是主键所以有索引,不会回表,这个查询非常快,得到一个id为a。
select * from table_test where years_per_slice='2018-09-12' limit 1;的时间会远远大于select id
2、确定删除范围
minId = a-limit/2;
maxId=a+limit/2;
为什么要要减掉减掉一半?因为select id的时候没有指定顺序,有可能不是按升序,所以通过减一半的方式确保数据可以肯定完全删除完
3、用id和时间替代limit
delete table table_test where years_per_slice='2018-09-12' and id between minId and maxId;
这样删除速度会非常快。
网友评论