带有子查询的 MySQL UPDATE 查询永远存在

Posted

技术标签:

【中文标题】带有子查询的 MySQL UPDATE 查询永远存在【英文标题】:MySQL UPDATE query with subquery taking forever 【发布时间】:2010-06-30 08:33:48 【问题描述】:

我有一个 mysql UPDATE 查询需要很长时间才能完成。我是否错过了一种更简单的方法来实现相同的结果?

"UPDATE table2, table1
SET table2.id_occurrences = (SELECT SUM(IF(id = table2.id, 1, 0)) FROM table1)
WHERE table2.id = table1.id;"
table2 包含 id 的所有可能值,每个值只有一条记录。 table1 包含id 的部分值,但部分值存在多条记录。 我需要更新table2 中的记录,以显示id 对应值在table1 中出现的次数。上面的查询完成了这项工作,但是当 table1 包含 500 条记录,table2 30,000 条记录时,大约需要 3 分钟。我有更大的表要处理,所以这太长了:)

提前致谢。

【问题讨论】:

【参考方案1】:

我认为您可能没有必要加入更新...

UPDATE table2
    SET table2.id_occurrences = (SELECT COUNT(*) FROM table1
                                     WHERE table2.id = table1.id);

【讨论】:

确实如此。并确保每个表中的 id 列都有索引。 啊,是的,这要快得多。我现在看到了,我什至没有更新 table1。非常感谢。【参考方案2】:

避免子查询,使用连接:

UPDATE table2
LEFT JOIN table1 ON (table2.id = table1.id)
SET table2.id_occurrences = COUNT(table1.id)
GROUP BY table2.id

哦,UPDATE 不支持 GROUP BY。试试这个查询:

UPDATE table2
LEFT JOIN (
   SELECT id, COUNT(*) AS cnt FROM table1 GROUP BY id
) AS t1
ON (table2.id = t1.id)
SET table2.id_occurrences = t1.cnt

【讨论】:

谢谢。有没有特别的理由避免子查询?我很想看看这种方法和 Brian's/Jonathan's 之间的速度差异,这使查询时间从 150 秒减少到 20 秒,但我收到以下语法错误:#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP BY table2.id' at line 4 对主查询的每一行执行WHERE中的依赖子查询,这可能会导致相当多的附加查询。最好将查询重写为 JOIN。我做了那个查询,看起来 UPDATE 不支持 GROUP BY。所以我很快就会给你一个带有 JOINed 子查询的查询。加入的子查询只执行一次。 这个查询的执行时间是多少? 哇,好用,而且超级快!当使用 table1 中的 4,000,000 个条目和 table2 中的 30,000 个条目时,只需 70 秒即可完成。我不是懒惰,只是无法使用 MySQL 文档使其工作。我对任何其他语言文档都很好,但 MySQL 总是让我失望:D 感谢您的帮助。 在使用上述方法需要 20 秒的较小表上,这需要 1.7 秒。不过,性能影响似乎随着表大小呈指数增长,这是有道理的。【参考方案3】:

我会选择类似的东西:

UPDATE table2
SET id_occurrences = (SELECT count(*) FROM table1
                      WHERE table1.id = table2.id)

【讨论】:

如果我也能接受这个答案,我会的。感谢您的帮助,Brian 刚到那里 :) 他确实做到了!并使用几乎相同的代码。他们说,伟大的思想都一样。 ;)【参考方案4】:
UPDATE table2, table1 
SET table2.id_occurrences = (SELECT SUM(IF(id = table2.id, 1, 0)) FROM table1) 
WHERE table2.id in (select distinct table1.id from table1) AND table2.id = table1.id;

【讨论】:

以上是关于带有子查询的 MySQL UPDATE 查询永远存在的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL的UPDATE子查询,UPDATE时避免使用子查询

在 Django 的 ORM 中使用带有 UPDATE 的子查询

MySQL的更新语句update中可以用子查询吗?

MYSQL:当满足子查询的所有条件时,在 UPDATE 查询中设置值

mysql 的delete from 和update子查询限制

mysql 不支持 update 子查询更新