如何从大型MySQL表中移除重复的content文本数据
大型MySQL数据表content字段去重方案
⚠️ 重要提醒:操作前一定要全量备份数据表,避免数据丢失!针对大型表,优先选择对锁表影响小的方案,减少业务中断时间。
方案一:临时表重建法(推荐超大型表使用)
这个方案通过临时表存储需要保留的数据,再替换原表,锁表时间极短,适合数据量巨大的场景:
创建临时表,存储每个唯一content对应的保留ID
这里我们选择保留每个content最早创建的记录(用最小id),你也可以根据业务需求改成最大id:CREATE TABLE temp_unique_content AS SELECT MIN(id) AS keep_id FROM your_table_name GROUP BY content;如果表特别大,建议给临时表加索引提升后续操作速度:
ALTER TABLE temp_unique_content ADD INDEX idx_keep_id(keep_id);创建新表存储去重后的数据
为了避免直接修改原表带来的风险,我们先创建一个和原表结构完全一致的新表:CREATE TABLE new_your_table_name LIKE your_table_name;然后把需要保留的数据插入新表:
INSERT INTO new_your_table_name SELECT t.* FROM your_table_name t JOIN temp_unique_content tu ON t.id = tu.keep_id;替换原表
这一步锁表时间很短,建议在业务低峰期操作:RENAME TABLE your_table_name TO old_your_table_name, new_your_table_name TO your_table_name;确认数据没问题后,再删除旧表:
DROP TABLE old_your_table_name;
方案二:DELETE JOIN直接删除(适合中型表)
如果你的表数据量不算超大,且能接受短时间锁表,可以用这个更直接的方法,但一定要先给content字段做优化索引:
新增哈希索引字段(解决longtext无法直接建普通索引的问题)
longtext类型无法直接创建普通索引,我们可以新增一个存储content哈希值的字段,用来加速分组查询:ALTER TABLE your_table_name ADD COLUMN content_md5 VARCHAR(32) AFTER content; UPDATE your_table_name SET content_md5 = MD5(content); ALTER TABLE your_table_name ADD INDEX idx_content_md5(content_md5);执行删除操作
删除重复记录,保留每个content对应的最小id记录:DELETE t1 FROM your_table_name t1 JOIN your_table_name t2 ON t1.content_md5 = t2.content_md5 AND t1.id > t2.id;(这里用content_md5关联比直接用content更快,避免全表扫描)
可选:删除临时哈希字段
如果不需要这个字段,去重完成后可以删掉:ALTER TABLE your_table_name DROP COLUMN content_md5;
方案三:窗口函数法(MySQL 8.0+适用)
如果你的MySQL版本是8.0及以上,可以用窗口函数更简洁地标记重复记录,然后删除:
- 标记重复记录
先查询出所有重复记录的id:
确认这些是要删除的记录后,执行删除:SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY content ORDER BY id) AS rn FROM your_table_name ) t WHERE rn > 1;
注意:这个方法对于超大型表可能会有性能问题,因为子查询会占用较多内存,建议先测试小范围数据。DELETE FROM your_table_name WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY content ORDER BY id) AS rn FROM your_table_name ) t WHERE rn > 1 );
内容的提问来源于stack exchange,提问作者bestestefan
相关产品推荐
相关产品推荐

