从大型mysql表中删除重复的TEXTS

时间:2018-03-19 01:09:21

标签: mysql sql

我有mysql表,它有结构

+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| content    | longtext         | NO   |     | NULL    |                |
| valid      | tinyint(1)       | NO   |     | NULL    |                |
| created_at | timestamp        | YES  |     | NULL    |                |
| updated_at | timestamp        | YES  |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+

我需要删除content列的重复条目,如果不是longtext,一切都会很简单,主要问题是该列中的条目长度从1个字符到12,000个以上字符不等,我有超过4,000,000个条目,像select id from table where content like "%stackoverflow%";之类的简单查询需要15秒来执行,删除重复条目的最佳方法是什么,而不是等待2天执行查询?

1 个答案:

答案 0 :(得分:1)

md5是你的朋友。使用hashvaluesid的列创建单独的hash表(以避免与生产中的此表锁定/争用)。此表的主键实际上应该是hash列,而不是id

创建新的空表后,使用MySql的md5()函数从原始数据中填充新表格,原始idmd5(content)字段值。如果有必要,您甚至可以批量填充表格,如果需要花费太长时间或减慢太多而无法立即完成所有操作。

当新表格完全填充数据时,您可以JOIN将其自身填充为:

SELECT h1.*
FROM hashvalues h1
INNER JOIN hashvalues h2 on h1.hash = h2.hash and h1.id <> h2.id

这比直接比较content要快 MUCH ,因为数据库只需要比较预先计算的哈希值。我期待几乎立刻跑。它会告诉您哪些记录潜在重复。仍然存在散列冲突的可能性,因此您还需要将其与原始数据进行比较以确定,或者在新表中包含originalcontent列,您可以将其与上面的查询一起使用。完成后,您将知道要删除哪些记录。

如果您可以在原始表中添加列,以便在每次更改时md5()字段的content哈希值保持最新,则此系统可能会更好。如果您拥有合适的存储引擎,Generated Column将适用于此。否则,您可以使用触发器。此列允许您根据需要重新运行重复项检查,而无需使用单独的表进行所有额外工作。

最后,还有Sha()Sha1()Sha2()函数可能更具抗冲突性。但是,md5()将更快,并且额外的碰撞阻力不足以避免也需要比较原始数据。这也不是碰撞潜力很重要的安全情况,因此md5()是更好的选择。毕竟,这些都不是密码。