删除范围内的十亿条记录与精确 ID 查找 MYSQL

Posted

技术标签:

【中文标题】删除范围内的十亿条记录与精确 ID 查找 MYSQL【英文标题】:Deleting Billion records in a range vs exact ID lookup MYSQL 【发布时间】:2021-05-21 20:00:13 【问题描述】:

我有一个大约 700GB 的数据库表,其中有 1 Billion 行,数据大约是 500GB,索引是 200GB, 我正在尝试删除 2021 年之前的所有数据, 2021 年大约有 298,970,576 行,还有 708,337,583 行剩余。

要删除它,我在我的 python shell 中运行一个不间断的查询

DELETE FROM table_name WHERE id < 1762163840 LIMIT 1000000;

id -> 1762163840 代表 2021 年的数据。删除 100 万行大约需要 1200-1800 秒。

有什么办法可以加快这个速度,因为目前的方式已经运行了 15 天以上,到目前为止没有太多的数据删除,而且会做更多的天。

我想如果我只用我要删除的所有记录的 id 制作一个表,然后做一个精确的映射,比如

DELETE FROM table_name WHERE id IN (SELECT id FROM _tmp_table_name);

会很快吗?会比先用所有记录新建一个表然后删除它更快吗?

数据库在 RDS 上设置,实例类为 db.r3.large 2 vCPU 和 15.25 GB RAM,仅运行 4-5 个连接。

【问题讨论】:

【参考方案1】:

如果你有足够的空间,我建议重新创建你想要保留的数据:

create table keep_data as
    select *
    from table_name
    where id >= 1762163840;

然后你可以截断表格并重新插入新数据:

truncate table table_name;

insert into table_name
    select *
    from keep_data;

这将重新创建索引。

缺点是重新插入数据仍需要一段时间(重命名keep_data 会更快)。但它应该比删除行快得多。

与。 . .这将使您有机会对表进行分区,以便可以更快地处理未来的删除。如果你有这么大的表,你应该研究一下表分区。

【讨论】:

交换两个表名比截断并复制回来要好。 是的,如果您当前的数据量小于存档数据量,则将符合条件的数据插入新表,然后将该表重命名为主表名称会非常有效。【参考方案2】:

大删除的多种技术:http://mysql.rjweb.org/doc.php/deletebig

它指出LIMIT 1000000 不必要地大,并导致比预期更多的锁定。

从长远来看,PARTITIONing 将是有益的,它提到了这一点。

如果您使用 Gordon 的技术(根据需要重建表格),您将在很长一段时间内无法访问该表格;我提供了一个基本为零停机时间的替代方案。

id IN (SELECT...) 可能非常慢 - 既是因为 in-SELECT 的效率低下,也是因为 DELETE 将保留大量行以实现事务完整性。

【讨论】:

以上是关于删除范围内的十亿条记录与精确 ID 查找 MYSQL的主要内容,如果未能解决你的问题,请参考以下文章

我想在oracle数据库中插入十亿条记录

将 s3 中跨 CSV 文件的数十亿条记录推送到 MongoDb

处理数十亿条记录的推荐数据库类型

如何使用mongo在sinatra的handsontable中轻松加载数十亿条记录?

面试题之十亿条记录,怎么获取出现最多的前十个

第20篇-不和谐如何索引数十亿条消息