面试官:删1000万条数据?别用 DELETE!

面试官:删1000万条数据?别用 DELETE!
最新回答
慌屿

2024-02-18 09:18:11

回答

在处理千万级大表快速删除大量数据时,需从问题规避、预演准备、方案选择和后置处理四个方面系统回答,具体思路如下:

一、一次性直接删除大量数据的风险

直接执行大事务删除可能引发以下问题:

  • 锁表与业务卡顿:大事务会长时间锁定表,阻塞其他查询和写入操作,导致业务接口超时或页面卡顿。例如删除1000万条数据耗时2小时,期间用户无法下单或查询。
  • 事务日志膨胀:数据库需记录所有删除操作的事务日志,日志文件可能暴涨至撑满磁盘空间,导致数据库崩溃。例如删除1亿条数据时日志增长至500GB。
  • CPU与I/O资源耗尽:删除操作需更新索引、触发约束检查和触发器逻辑,导致CPU飙升至100%,正常查询延迟从2ms升至10秒。
  • 主从延迟:主库删除操作需同步到从库,大事务可能导致复制延迟,影响依赖从库的业务(如报表、备份)。例如主库删除耗时2小时,从库延迟3小时。
  • 回滚困难:删除中途失败或主动取消时,事务回滚可能比删除更耗时,甚至导致数据损坏。例如删除5000万条数据1小时后中断,回滚需2小时。
二、删除前的预演与准备

在执行删除前需完成以下准备工作:

  • 评估数据量与方案选择

    删除大部分数据(如90%以上):采用新建表+删除旧表法,速度更快。

    删除小部分数据(如10%以下):直接分批删除更省事。

  • 优化删除条件索引:确保删除条件字段(如日期、ID范围)有索引,避免全表扫描。例如通过索引加速按时间范围删除旧数据。
  • 数据备份:执行完整备份或增量备份,防止误删导致数据丢失。例如分批删除时记录每批删除的ID范围,便于回滚。
三、大批量数据删除的常见方案

根据场景选择以下高效方案:

  • 分批删除

    通过LIMIT分批删除,避免单次事务过大。例如:DELETE FROM tianluo_tab WHERE 条件 LIMIT 1000;

    循环执行并短暂停顿(如0.1秒),关闭自动提交减少事务开销:SET autocommit=0;-- 循环执行删除语句COMMIT;

  • 分区表法

    对按时间或范围分区的表(如日志表),直接删除整个分区:ALTER TABLE table DROP PARTITION partition_name;

    优点:秒级完成,无需逐行删除;条件:需提前设计分区键。

  • 新建表替换旧表

    适用于删除超过50%数据的场景:

    创建新表并插入保留数据:CREATE TABLE new_table AS SELECT * FROM old_table WHERE 保留条件;

    重命名表快速切换:RENAME TABLE old_table TO old_table_backup, new_table TO old_table;

    确认无误后删除备份表:DROP TABLE old_table_backup;

    优点:速度极快,几乎不锁表;缺点:需重建索引和外键。

  • TRUNCATE替代DELETE

    清空整个表数据时使用TRUNCATE,直接释放空间而非逐行删除:TRUNCATE TABLE tianluo_tab;

  • 加速技巧

    使用工具如MySQL的pt-archiver自动分批删除。

    在低峰期操作,避免业务冲突。

    优先删除冷数据(如归档旧数据后再删除)。

四、删除后的后置处理

删除完成后需进行以下验证与优化:

  • 数据验证

    确认目标数据已删除(如按时间条件查询残留数据):SELECT COUNT(*) FROM tianluo_tab WHERE create_time < '2025-05-02';

    随机抽查未删除数据,确保未误删有效记录(如status='正常'的记录)。

    检查关联系统功能(如报表、API接口)是否正常。

  • 监控与日志

    监控数据库性能(CPU、内存、I/O)是否恢复正常。

    检查慢查询日志,确认无索引失效问题。

    记录操作日志(时间、数据量、操作人),便于审计。

  • 资源释放

    回收磁盘空间(如MySQL的OPTIMIZE TABLE或PostgreSQL的VACUUM FULL,但需谨慎使用以避免锁表)。

通过以上步骤,可系统化解决千万级大表删除数据的问题,兼顾效率与安全性。