【问题标题】:Improve the performance of select first then insert to avoid duplicate record (in mysql & php)?提高先选择然后插入的性能以避免重复记录(在mysql和php中)?
【发布时间】:2020-01-05 04:21:28
【问题描述】:

为了避免重复插入,我知道我可以在 mysql 中使用“INSERT IGNORE”或“INSERT ... ON DUPLICATE KEY UPDATE”。

但我正在使用 laravel,我知道 firstOrCreate 不会那样做。它首先进行 SELECT 以查看条目是否存在,并且仅当 SELECT 没有返回记录时才进行 INSERT。我想这是因为DUPLICATE KEY UPDATE 是 MySQL 特有的。

从性能的角度来看,我先选择然后插入真的很糟糕吗?与“INSERT IGNORE”或“INSERT ... ON DUPLICATE KEY UPDATE”相比,这会对性能造成多大影响?

不使用 firstOrCreate 并将我自己的 php 代码写入“INSERT IGNORE”或“INSERT ... ON DUPLICATE KEY UPDATE”是否值得麻烦?

【问题讨论】:

  • 问题:如果插入因重复问题而失败,您希望发生什么?你真的要更新,还是仅仅失败就足够了?
  • 如果选择只使用主键并且您有合理数量的行,我会说一般使用中的性能影响可以忽略不计。虽然您可能会遇到转储问题,但在这种情况下,您通常不介意额外的时间来完成任务。
  • 你可以使用 Laravel DB Statement 来编写你自己的查询。如果索引正确,firstOrCreate 不会产生那么多问题。
  • @TimBiegeleisen 我只需要插入忽略。但我对先选择然后插入的性能影响感兴趣。
  • @mikiqex 您是否有实际数据来备份您的陈述,即“一般使用中的性能影响可以忽略不计”。 ?

标签: php mysql laravel insert


【解决方案1】:

也许在 mysql 中尝试 REPLACE:

REPLACE ...

【讨论】:

  • 添加更多描述
【解决方案2】:

假设您只需要 INSERT INTO ... IGNORE 功能,我建议您只在相关表上创建一个唯一索引。

ALTER TABLE yourTable ADD CONSTRAINT cnstr UNIQUE KEY (col1, col2, ...);

有了这个,任何插入重复记录的尝试都会在 PHP 端导致应用程序错误,您可以轻松捕获和处理。

在尝试插入之前先进行插入以检查是否存在重复项的问题在于,只有在确保从选择时间到插入完成时间之间没有其他 DML 活动发生在表中的情况下,这样的逻辑才会起作用.否则,可能会出现以下情况:

process1: SELECT to check if record exists (assume it does not)
process2: INSERT record (which process1 wants to insert)
process1: INSERT same record (now a duplicate exists)

换句话说,您的 PHP 应用程序会“认为”不存在重复记录,然后插入记录。但是,在它的 select 和 insert 之间的时间里,另一个进程恰好插入了相同的记录。

为避免这种情况,我相信您需要类似可序列化事务的东西。但是,使用唯一约束更加简洁,并且主要由数据库来处理这个责任。

【讨论】:

  • 您好,感谢您回答我的问题。那么先选择再插入对性能的影响呢?它真的像我得到的其他评论一样微不足道吗?
  • 这并不是真正的大问题。更大的问题是该方法有一个严重的缺陷,即您的选择可能会通过,但您可能仍然以重复结束。为了一个简单的解决方案,让 MySQL 处理这个问题。
猜你喜欢
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 2018-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多