【问题标题】:What would cause this SQL insert to run very slowly?什么会导致此 SQL 插入运行非常缓慢?
【发布时间】:2016-03-14 16:10:15
【问题描述】:

我正在使用子查询来查找系统中的重复行。

SELECT * FROM locations l2 WHERE l2.id IN (
    SELECT min(l1.id) FROM locations l1
    GROUP BY l1.address, l1.city, l1.industry_id
    HAVING count(*) > 1
)

这个查询执行得相当快,大约 0.4 秒。但是,如果我尝试在它周围包裹一个插入:

INSERT INTO duplicate_locations (
    SELECT * FROM locations l2 WHERE l2.id IN (
        SELECT min(l1.id) FROM locations l1
        GROUP BY l1.address, l1.city, l1.industry_id
        HAVING count(*) > 1
    )
)

此查询需要 6 分钟 100 行。

系统上的其他一切都运行良好。表的结构相同,MyISAM,MariaDB 5.5(没有 EXPLAIN INSERT)。起初我认为这是一个表问题,但我尝试了一个新表并得到了类似的结果,所以查询肯定有问题。磁盘很好,运行时都是 CPU 负载。我能够在几秒钟内复制整个位置表(数万行)。

【问题讨论】:

  • 这不是您插入结果的方式;至少这不是我所见过的。应该是INSERT INTO table SELECT ....(没有括号)...虽然我想它可能会忽略它们。

标签: mysql mariadb where-in


【解决方案1】:

MySQL WHERE 子句中的子查询通常是性能杀手,除了最简单的情况外,或者在不使用它们会导致异常复杂查询的情况下,应避免使用它们,请尝试以下方法:

INSERT INTO duplicate_locations 
    SELECT l0.* FROM locations AS l0
    INNER JOIN (
        SELECT min(id) AS firstID
        FROM locations
        GROUP BY address, city, industry_id
        HAVING count(*) > 1
    ) AS firstL 
    ON l0.id = firstL.firstID
;

【讨论】:

  • 疯了,这是导致问题的原因。使用它的 SELECT 查询花费了相同的时间 (0.4s),但 100 行的 INSERT 也只花费了 0.4s。所以这绝对解决了它。我只需要将 SELECT * 替换为 SELECT l0.* 即可使列正确。
  • 更正了疏忽以供将来参考。很高兴它有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 1970-01-01
  • 2017-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多