删除 mysql 表上的重复项 [该表 > 2Gb]

Posted

技术标签:

【中文标题】删除 mysql 表上的重复项 [该表 > 2Gb]【英文标题】:Removing duplicates on mysql table [the table is > 2Gb] 【发布时间】:2019-09-18 10:08:00 【问题描述】:

问题 - 我们的表格中有许多重复的行,这使得计算不准确

解决方案 我试过了 - 我写了一个删除内部连接查询,该查询将删除重复项(根据我的研究,这是最快的方法),在 staging 上对其进行了测试,它工作正常,在生产希望最多能持续 1-2 天,

这是我使用的查询:

DELETE t1 FROM table t1
    INNER JOIN
table t2 
WHERE t1.id > t2.id 
AND t1.col1 = t2.col1
AND t1.col2 = t2.col2
AND t1.col3 = t2.col3
AND t1.col4 = t2.col4

解决方案的问题 -

我预计查询会运行几个小时或 2-3 天,但当我尝试整个表的这个解决方案时,它花了 4 天时间,它仍然在运行,我不得不终止该进程。

查询已经运行了 4 天,它仍然在运行,我尝试了一个较小的表,它是我原始表的一部分,但又花了几个小时。我无法在我的表上运行数周的查询,因为我要在这张表上进行大量计算并且我不希望我的表被锁定。

【问题讨论】:

你对这些列有索引吗?如果不尝试添加复合索引,请尝试。 【参考方案1】:

从一个表中删除大量的行是非常昂贵的。我建议使用您想要的行创建一个新表,然后(也许)重新填充原始表。

你可以从:

CREATE TABLE temp_t AS
    SELECT t1.*
    FROM t t1
    WHERE t1.id = (SELECT MIN(t2.id)
                   FROM t t2
                   WHERE t2.col1 = t2.col1 AND
                         t2.col2 = t2.col2 AND
                         t2.col3 = t2.col3 AND
                         t2.col4 = t2.col4
                  );

要使其在合理的时间内工作,您需要在t(col1, col2, col3, col4) 上建立索引!索引非常重要(可能需要一些时间来构建)。

然后,您可以决定是否要重新填充原始表格。如果您已经验证以上内容正确,您可以这样做:

truncate table t;

insert into t
    select * from temp_t;

当然,你应该在做这样的事情之前备份你的表/数据库。

【讨论】:

我也创建了另一个表,但没有尝试索引。我会放索引并试一试,非常感谢。

以上是关于删除 mysql 表上的重复项 [该表 > 2Gb]的主要内容,如果未能解决你的问题,请参考以下文章

删除左表上的重复项,同时在右表SELECT JOIN上保留重复项

删除连接表的重复记录并修复相关表上的外键

MYSQL - 将具有多个重复值的行组合起来,然后删除重复项

mysql 索引作用范围

无法删除表:外键约束失败

每天晚上被删除的表上的 Mysql 索引