最近工作中,遇到了要删除一些相关库的数据信息,涉及的数据有点多。
实际场景是这样的,公司的一个电商项目,电商为卖家准备了报表的相关数据,报表业务在实现时,将一些订单信息冷库备份到报表的库中,然后再在报表的库中进行相关的报表相关业务的计算。
由于项目起步时间晚,客户留存率不高,就遗留了相当大的一部分流失用户的数据,现在,开始着手删除这些已经不再使用系统的客户的历史数据。
数据库中做了分表将相关的公司分到不同的表中,光trade这张表,同个公司下平均就有百万级的数据,要根据公司的id去delete这些数据,肯定是慢的要死的。
最终,结合现有情况选择了最简单粗暴的方式,trade表中现有很多组合索引,找了一个符合这次删除要求的组合索引,在where 语句中将这个组合索引搞进来。
delete from trade where company_id = 233; 本来是这样的一个语句,按照时间范围来走组合索引,就变成了delete from trade where company_id = 233 and date > "", (现有组合索引为company_Id 和 date),防止只用companyId 优化器选择不了最优的sql。
另外,要注意下,a.这些是冷数据是直接删除的,如果还是有更新,要加limit,这样防止大的事务导致锁冲突。
b. 删了数据,只是标记了数据删除,会有数据空洞,这样会发现数据库的实际物理空间可能会没有太大的变化,记得后面要重建表来收缩空间,alter table A engine = innodb命令,5.5的实现相当于手动额外建立了个新表,将保留的数据搞过去。5.6进行了大量的优化,感兴趣的可以研究下5.6版本引入了Online DDL对这个流程进行的优化
c. 如果是主从架构,注意下删大量数据,可能会导致的主从不一致的问题