5

我目前有一个大约 2000 万行的 MySQL 表,我需要对其进行修剪。我想删除updateTime(插入时间戳)超过一个月前的每一行。我没有亲自对表的顺序进行过任何改动,所以数据应该按照插入的顺序,并且UNIQUE在两个字段上有一个键,idupdateTime。我将如何在短时间内做到这一点?

4

4 回答 4

15

您可以承受多少停机时间?行有多大?你要删多少?

简而言之,删除行是您可以对表执行的最昂贵的操作之一。总的来说,这只是一件可怕的事情。

如果您不必这样做,并且您有足够的磁盘空间,并且您的查询不受表大小的影响(索引良好的查询通常会忽略表大小),那么您可能就可以不用管它了。

如果您有机会并且可以使表格脱机(并且您正在删除表格的很大一部分),那么您最好的选择是将要保留的行复制到新表格中,删除旧表格,重命名旧名称的新名称,然后重新创建索引。

否则,你几乎会被好的'ol delete 所困。

于 2010-07-11T16:54:14.380 回答
13

有两种方法可以删除大量行。首先有一个明显的方法:

DELETE FROM table1 WHERE updateTime < NOW() - interval 1 month;

第二种(稍微复杂一点)方法是创建一个新表并复制您要保留的数据,截断旧表,然后将行复制回来。

CREATE TABLE table2 AS
SELECT * FROM table1 WHERE updateTime >= NOW() - interval 1 month;

TRUNCATE table1;

INSERT INTO table1
SELECT * FROM table2;

当您要删除大量行并且希望保留相对较小的行数时,使用比with子句TRUNCATE快得多。DELETEWHERE

于 2010-07-11T16:51:26.617 回答
0

使用限制拆分删除可能会加快进程;

我不得不删除 10M 行并发出命令。它几个小时都没有回应。

我杀死了查询(花了几个小时)

然后拆分删除。

DELETE from table where id > XXXX limit 10000;
DELETE from table where id > XXXX limit 10000;
DELETE from table where id > XXXX limit 10000;
DELETE from table where id > XXXX limit 10000;

然后我在一个文件中复制了这个语句并使用了这个命令。

mysql> source /tmp/delete.sql 

这要快得多。

您也可以尝试使用 pt-tools 等工具。和pt存档。

于 2013-03-22T22:35:07.067 回答
0

实际上,即使您不能让表长时间离线,您仍然可以使用“重命名表”技术来摆脱旧数据。

停止写入表的进程。

rename table tableName to tmpTableName;
create table tableName like tmpTableName;
set @currentId=(select max(id) from tmpTableName);
set @currentId=@currentId+1;
set @indexQuery = CONCAT("alter table test auto_increment = ", @currentId);
prepare stmt from @indexQuery;
execute stmt;
deallocate prepare stmt;

启动写入表的进程。

insert into tableName
select * from tmpTableName;
drop table;

对 tableName 的新插入将从正确的索引开始;旧数据将插入正确的索引中。

于 2013-08-10T14:26:28.693 回答