删除范围内的十亿条记录与精确 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的主要内容,如果未能解决你的问题,请参考以下文章
将 s3 中跨 CSV 文件的数十亿条记录推送到 MongoDb