【问题标题】:Fast delete duplicate records in MySQLMySQL快速删除重复记录
【发布时间】:2015-12-29 17:42:36
【问题描述】:

我正在尝试将非常大的 SQL 转储(大约 3700 万行)导入 InnoDB 表。有大量重复项,我想要实现的是,在不改变实际转储的情况下想要防止重复行插入。 email 字段可能有重复项。我尝试了以下操作:将整个转储导入数据库后,我尝试执行以下 SQL:

set session old_alter_table=1;
ALTER IGNORE TABLE sample ADD UNIQUE (email);

但是第二个查询工作了大约 1 小时,然后我取消了这个查询。

消除重复的正确方法是什么?

我有几个想法:

  • 也许在开始导入之前创建具有唯一索引的表并在插入时防止重复而不损害整个过程?
  • 也许在导入转储以选择不同的电子邮件并插入另一个表之后?

【问题讨论】:

标签: mysql sql duplicates distinct


【解决方案1】:

如下编辑转储文件:

  1. 修改CREATE TABLE语句以在email字段上添加唯一键,或在其后添加ALTER TABLE语句。

  2. 找到所有INSERT INTO sample 语句,并将它们更改为INSERT IGNORE INTO sample

您也可以使用管道执行第 2 步:

sed 's/INSERT INTO sample/INSERT IGNORE INTO sample/' sample_table.dump | mysql -u root -p sample_db

如果文件太大而无法编辑添加ALTER TABLE语句,我建议您使用--no-create-info选项创建转储mysqldump,并在加载之前手动创建表(使用唯一键)转储文件。

【讨论】:

  • 1.5 GB 文本文件。如何替换所有出现的?:)
  • 我已经更新了答案以展示如何在不编辑转储文件的情况下执行此操作。
【解决方案2】:

来自 .dump 文件

导入时,“强制”使用-f

mysql -f -p < 2015-10-01.sql

这会导致在遇到错误后继续导入,如果您在导入之前创建唯一键约束,这在这种情况下很有用。


来自 .csv 文件

如果您使用“加载数据”,请使用“忽略”,例如:

LOAD DATA LOCAL INFILE 'somefile.csv' IGNORE
    INTO TABLE some_db.some_tbl
        FIELDS TERMINATED BY ';'
               OPTIONALLY ENCLOSED BY '"'
        LINES TERMINATED BY '\n'
    (`somefield1`,`somefield2`);

根据documentation

如果您指定 IGNORE,则与唯一的现有行重复的行 键值被丢弃。

这需要您在导入之前创建唯一键约束,这在空表上会很快。

【讨论】:

  • 我有 .dump 文件,它由 sql create table 和 insert 命令组成。我只是像mysql -u root -p sample_db &lt; sample_table.dump 一样导入在Linux 中使用VIM 编辑1.4 GB 的文本文件非常困难。这就是为什么要寻找其他解决方案,这些解决方案是在导入之后或不通过编辑这个大文件。
  • force 与这个问题有什么关系?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-17
相关资源
最近更新 更多