繁体   English   中英

从巨大的MySQL innoDB表中删除记录

[英]Deleting Records from huge MySQL innoDB Table

我知道这个问题已被问了一百次,但不幸的是,这些答案都没有帮助,因为大多数都是很多年,它应该证明另一个问题的合理性。

我有两个表, records +140kk rows/+24GBextra +89kk rows/+70GB

每个extra行都有一个与records的外键关系,索引在两个表之间正确设置。 records的删除会将删除级联到相关的extra行。

我需要在制作过程中清除旧记录。 运行DELETE FROM records WHERE WHERE created < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) ORDER BY id LIMIT 1000; 需要无休止的(我在20分钟后将它杀死了,它仍处于init )。 使用SELECT执行相同操作只需几毫秒即可完成。

由于SELECT是那么快我用id IN (SELECT id subquery^)尝试它,不幸的是没有改变一个东西,所以我在15分钟后杀了它。

由于删除单个记录很快,我最终完成了这项工作:

for i in `seq 1 100000`; do
    mysql database -e "SELECT id FROM records WHERE created < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 30 DAY)) ORDER BY id LIMIT 1000;" | sed 's;/|;;g' | awk '{if(NR>1)print "DELETE FROM records WHERE id = ",$1,";" }' | mysql database;
    now=$(date +"%Y/%m/%d %T")
    echo "[ $now ] $i.000"
done

这可以在开始时每秒处理一千条记录,但是在几次循环之后它每10-20秒就会下降到一千条记录。 由于我需要清除100k行,这需要将近一个月的时间才能完成,这与清除记录的时间差大致相同,因此它永远不会完成(特别是因为有多个数据库需要这样做)。

数据库存储在SSD Crucial_CT500MX200SSD1 ,软件是带有InnoDB引擎的MariaDB 10.1 innodb_flush_log_at_trx_commit设置为0以避免不必要的磁盘工具。

根据atop瓶颈是磁盘,CPU几乎正在睡眠,大部分内存都在系统缓存中。

结构转储: https//gist.github.com/Slind14/0da34e09dba91cf411db2ead5ad666ef

请参见http://mysql.rjweb.org/doc.php/deletebig

它讨论了从大表中有效删除大量行的各种方法。

可能效果最好的是基于PRIMARY KEY (它有这样的?)遍历表,删除该块中符合条件的行。

这是有效的原因是它一次看100行,与它们一起工作,然后继续前进到接下来的100行。 相反,使用LIMIT和无界WHERE子句可能需要反复扫描相同的行。

你提到了JOIN 根据成本的高低,100可能是一个很好的限制。 如果JOIN不是太繁重,也许1000会很好。

如果这将是一个重复的任务,请考虑使用PARTITIONing以便DROP PARTITION可用于“立即”执行契约。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM