大数据量去重是MySQL中常见的性能挑战,尤其当表记录达到百万甚至千万级别时,常规的 DISTINCT 或 GROUP BY 可能导致查询慢、锁表、内存溢出等问题。以下是几种实用且高效的处理方案。
1. 使用临时表 + GROUP BY 去重
对于大表去重,直接操作原表效率低。建议先将去重数据写入临时表,再替换或更新原表。
- 创建临时表存储去重结果 - 使用 GROUP BY 按关键字段聚合(如手机号、用户ID) - 添加必要索引提升分组效率 - 完成后重命名或导入主表示例:
CREATE TABLE temp_user AS SELECT MIN(id) as id, phone, name FROM user_table GROUP BY phone;
2. 分批处理避免锁表和内存压力
一次性处理千万级数据容易超时或崩溃,应按主键范围分批次处理。
- 按主键区间(如 id BETWEEN 1 AND 100000)循环处理 - 每批处理完成后提交事务 - 可结合脚本或存储过程自动执行优点:减少事务占用时间,降低对线上服务影响。
3. 利用唯一索引防止重复数据写入
预防优于治理。通过数据库约束从源头控制重复。
- 在关键字段上建立唯一索引(如 UNIQUE KEY idx_phone(phone)) - 插入时使用 INSERT IGNORE 或 ON DUPLICATE KEY UPDATE - 避免后续大规模清洗成本例如:
ALTER TABLE user_table ADD UNIQUE INDEX uk_phone (phone);
INSERT IGNORE INTO user_table (phone, name) VALUES ('13800138000', '张三');
4. 结合外部工具或中间表处理
当MySQL自身处理能力受限时,可借助外部手段。
- 导出数据到文件,用Python/Spark去重后再导入 - 使用ETL工具(如DataX、Kettle)进行清洗 - 利用Redis的Set结构实时判重(适用于高并发写入场景)适合离线批量清洗或实时写入去重需求。
基本上就这些。关键是根据数据量、业务场景和系统负载选择合适方式。线上操作前务必备份,测试环境验证流程。不复杂但容易忽略细节,比如索引缺失或事务过大。合理设计能显著提升效率。
