在MySQL中批量删除大型表


9

我有一个Notification表,其中包含1000个IOPS的Amazon RDS中的大约1亿行主机,我想删除一个月以上的行。

如果这样做DELETE FROM NOTIFICATION WHERE CreatedAt < DATE_SUB(CURDATE(), INTERVAL 30 day);,将使用所有IOPS,整个过程将花费数小时,并且由于“超出了锁定等待超时;尝试重新启动事务”,因此无法插入许多新条目。

我试图按照此处描述的方式进行操作:http : //mysql.rjweb.org/doc.php/deletebig 但是,我使用的是UUID而不是增量ID。

在不影响正在插入/更新的新数据的情况下,删除这些行的正确而有效的方法是什么?


您是正确的ypercube,我已予以纠正。感谢您指出!
天一聪

删除记录在更小的块,不会影响插入操作,我带环试了一下,它完成删除70000000纪录在不到一个小时rathishkumar.in/2017/12/...
Rathish

Answers:


11

制作一个临时表,切入和切出它,然后将最近30天的数据复制到其中。

#
# Make empty temp table
#
CREATE TABLE NOTIFICATION_NEW LIKE NOTIFICATION;
#
# Switch in new empty temp table
#
RENAME TABLE NOTIFICATION TO NOTIFICATION_OLD,NOTIFICATION_NEW TO NOTIFICATION;
#
# Retrieve last 30 days data 
#
INSERT INTO NOTIFICATION SELECT * FROM NOTIFICATION_OLD
WHERE CreatedAt >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);

在下班时间,丢下旧桌子

DROP TABLE NOTIFICATION_OLD;

这是执行像这样的DELETE的优点

  1. NOTIFICATION 通过在空表中切换来快速清空。
  2. NOTIFICATION 立即可用于新的INSERT
  3. 剩下的30天会重新添加到NOTIFICATION新的INSERT中。
  4. 删除旧版本NOTIFICATION不会干扰新的INSERT
  5. 注意:我建议您在进行表DELETE操作之前进行诱饵和切换:(请参阅我的2012年7月19日发布:在MySQL MEMORY表上优化DELETE查询

试试看 !!!


感谢Rolando的回复!MySql在内部如何处理删除表?首先删除所有列,然后删除表或其他?是否需要比删除那些克隆块更短的时间?
天一聪

我在登台应用此策略,重命名命令应该以“ RENAME TABLE”开头吗?
天一聪

如果我在事务块内使用它,是否会有所不同,请牢记锁定等待超时,如果我的实际表确实很大,现在已重命名并且必须将其删除,它也会有任何弊端
Muhammad Omer Aslam

1
在这种情况下,@ MuhammadOmerAslam的ibdata1文件(系统表空间)只会在撤消日志中增长。当ibdata1的文件大小开始变大时,尤其是这种情况(请参阅我的旧帖子dba.stackexchange.com/questions/40730/…)。您需要通过使用akuzminsky的答案中提到的pt-archiver来加倍小心,可以节制删除大块中的行,然后使用pt-online-schema-change ALTER TABLE ENGINE=InnoDB 来缩小表。
RolandoMySQLDBA

1
@MuhammadOmerAslam当您计划了停机时间时,以上方法将是完美的。跟随akuzminsky答案中的链接(percona.com/doc/percona-toolkit/LATEST/pt-archiver.html)。您可以使用pt-archiver归档数据,或者仅删除数据而不进行归档。
RolandoMySQLDBA

3

我最喜欢的是Percona Toolkit中的pt-archiver。它负责MySQL的负载,复制滞后。


感谢回复akuzminsky!我会仔细看看的。当我想使用pt-online-schema-change更改此通知表时,曾经尝试过Percona。但是,它需要SUPER权限才能进行更改,而RDS并未提供此权限。顺便说一句,你知道改变大桌子的好方法吗?
天一聪

@TianyiCong您有一个新问题:请作为一个新问题提出,并可能在此处用链接发表评论,不要在不是本网站工作原理的评论中提出。
杰克说请尝试topanswers.xyz 2014年

-2

创建表notification_temp作为select * from通知,其中CreatedAt <DATE_SUB(CURDATE(),INTERVAL 30天);

删除表通知;

重命名notification_temp TO NOTIFICATION;


而且这不会影响要插入/更新的新数据吗?我不这么认为。
Colin't Hart 2014年

此方法有2个问题:1)在DROP TABLE的持续时间内无法使用NOTIFICATION。2)CREATE TABLE错过了在插入期间发生的插入。
RolandoMySQLDBA 2014年

另一个问题:应该说RENAME TABLE notification_temp ...
RolandoMySQLDBA
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.