当前位置:首页 > 分享 > 正文

从 10 亿条数据中删除重复记录MySQL 中无任何索引情况下如何做到(十亿条数据快速查找)

在设计数据库时,我们根据最初的需求来设计,很少会考虑到异常庞大的数据量。但是当数据增长到比如上亿的时候,有时您可能会耗尽系统资源和大量的时间来处理一些问题。

问题描述:在表 TableY 上约有10 亿条记录。在列 `ColumnX` 包含重复记录,目前没有索引。我们要删除重复的记录。

以下是一些有助于从当前数据库的状态一步步操作来达到解决问题的步骤:

第 1 步:查找重复项

如果您认为运行以下查询可以得到重复记录的列表,那么您就错了,考虑记录数和非索引列。最好永远不要在数据库中运行此查询;这可能会影响现有数据库查询的性能。

SELECT count(*) AS Total, ColumnX FROM TableY GROUP BY ColumnX HAVING Total >= 2;

注意:这个查询需要几天时间才能返回列表。

如果您考虑过上述查询,您现在就会明白,使用现有设置获取重复记录列表并不容易。

这将我们带到了第一步,即添加常规索引。这不需要太多时间来完成。完成它需要30-60分钟。

CREATE INDEX `idx_ColumnX` ON TableY(ColumnX);

现在,我们已经在 ColumnX 上添加了常规索引,重新运行上面的查询来获取重复记录的列表。这次花费的时间< 30 分钟

第 2 步:删除重复项

查找重复记录很容易与删除重复记录进行比较。这里涉及到很多因素,删除哪些重复记录?诸如“LastUpdated”、“CreatedDate”、其他列的重要信息等因素可能会影响决定删除适当的记录。

删除记录后你可能仍然没有信心,可能有很多有价值的信息是你以后需要的。

考虑到上述挑战,您有以下两种选择:

  1. 删除记录;其他记录或列不包含任何有价值的信息。
  2. 或者为重复记录创建一个备份表,以便您将来可以使用它。

这样,这里是创建一个简单备份表的查询:

CREATE TABLE IF NOT EXISTS `BackUpTableY` (`ID` varchar(255) NOT NULL,`ColumnA` varchar(255) NOT NULL,`ColumnB` varchar(255) NOT NULL,`ColumnC` tinyint(1) NOT NULL,`ColumnX` varchar(255) DEFAULT NULL,`CreatedDate` datetime(3) NOT NULL,`LastUpdated` datetime(3) NOT NULL,PRIMARY KEY (`ID`),KEY `idx_ColumnX` (`ColumnX`) USING BTREE,KEY `idx_ColumnA` (`ColumnA`));

现在,将所有重复记录插入上表:

INSERT INTO BackUpTableYSELECT TY.*FROM TableY AS TYINNER JOIN(SELECTmax(LastUpdated) AS LatestUpdated,count(*) AS Total,ColumnXFROM TableYGROUP BY ColumnXHAVING Total >= 2)AS Tbl ON TY.ColumnX = Tbl.ColumnXAND TY.LastUpdated != Tbl.LatestUpdated;

现在,最后的步骤 - 删除重复记录。同样,您在选择其中一种方法时需要格外小心:

  1. 使用单个 DELETE 命令删除所有重复记录:这将在这些记录范围内添加一个锁,并可能影响整体数据库性能。
  2. 为每条记录创建单独的 DELETE 语句并批量运行它们:这种方法可能需要额外的工作,但不会影响整体数据库性能。

两种方法都各有利弊。根据您的数据集选择最适合您的。

第 3 步:添加唯一索引

一旦添加了常规索引并删除了重复记录,我们就需要添加唯一索引以防止以后又添加了重复记录,即。

CREATE UNIQUE INDEX `idx_Unique_ColumnX` ON `TableY`(`ColumnX`);

由于 ColumnX 已经有常规索引,添加唯一索引不会花费太多时间,即 ~5 分钟。

至此,我们结束了这次学习。