【问题标题】:Add only new records in MySQL via script通过脚本仅在 MySQL 中添加新记录
【发布时间】:2012-07-18 13:24:46
【问题描述】:

我有一个大型数据库,我正在尝试通过 perl 进行更新。要添加的信息来自我无法控制的 csv 文件(但它是受信任的——它来自我们公司的不同部分)。对于文件中的每条记录,我需要添加它(如果它不存在)或什么都不做(如果它存在)。添加记录由通常的INSERT INTO 组成,但在此之前,必须为特定条目运行特定的UPDATE

为了具体起见,假设该文件有 10,000 个条目,但其中 90% 已经在数据库中。导入记录的最有效方法是什么?我可以看到一些明显的方法:

  • 从数据库中提取所有此类记录,然后检查文件中的每个条目的成员资格。缺点:大量数据传输,可能足以让服务器超时。
  • 从文件中读取条目,并使用RLIKE 'foo|bar|baz|...' 查询(或stuff = 'foo' || stuff = 'bar' || ... 查询,但这似乎更糟)发送查询。缺点:查询量很大,可能足以阻塞服务器。
  • 读入文件,为每个条目发送一个查询,然后在适当的时候添加它。缺点:数以万计的查询,非常慢。

除了UPDATE 要求之外,这似乎是一个相当标准的问题,大概有一个标准的解决方案。如果有,它可能会适应我的情况,适当使用auto_increment 主键上的测试。

【问题讨论】:

    标签: mysql sql perl optimization query-optimization


    【解决方案1】:

    标准解决方案是使用INSERT IGNORE,如果插入由于约束而失败,则不会引发错误。这对您没有多大用处,因为在您知道INSERT 将起作用之前,它不会让您有机会执行UPDATE。但是,如果您可以在之后进行更新,这是理想的:只需 INSERT IGNORE 每条记录,然后在成功时执行 UPDATE

    如果一条记录已经存在,则表示数据库中已经有一条具有匹配唯一键的记录,所以我不明白RLIKE的提议,它一定会很慢。 p>

    我会使用 Perl 对每条记录使用 SELECT count(*) FROM table WHERE key = ? 对 CSV 文件进行 grep,并删除结果非零的任何内容。

    然后对过滤后的 CSV 数据中剩下的所有内容执行 UPDATEINSERT

    【讨论】:

    • 不过,我输入的所有字段都不是主键。主键是我提到的auto_increment 字段。所以UPDATE IGNORE 不起作用。
    • 如果有记录匹配我正在插入的字段。因此,如果我有 INSERT INTO tbl (foo, bar, baz) VALUES ('f', 'b', 'b'),如果有 foo='f'、bar='b' 和 baz='b' 的条目,我不想添加记录。
    • @Charles: 然后我会ALTER TABLE tbl ADD UNIQUE INDEX (foo, bar, baz) 然后INSERT IGNORE INTO tbl
    • 不幸的是,这不是一个选项:数据库被一个(大型)外部应用程序使用,需要按现在的方式布置表。
    【解决方案2】:

    如果您在迭代列表时不断刷新数据,则无需使服务器超时。

    【讨论】:

      猜你喜欢
      • 2017-03-13
      • 1970-01-01
      • 1970-01-01
      • 2012-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-12
      • 1970-01-01
      相关资源
      最近更新 更多