带有子查询的 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 查询中设置值