使用MySQL“in”导致循环?
当我隔离这个查询时:
SELECT `Tagged`.`contact_id`
FROM contacts_tags AS Tagged LEFT JOIN tags AS Tag ON (`Tagged`.`tag_id` = `Tag`.`id`)
WHERE `Tag`.`id` = 137;
我得到:
+------------+
| contact_id |
+------------+
| 3519 |
| 17080 |
+------------+
但是当我使用“IN”将它与更大的查询结合起来时,我得到某种递归循环,我的数据库开始消耗处理能力,直到超时。
SELECT `Contact`.*
FROM `contacts` AS `Contact`
WHERE `Contact`.`id` in
(SELECT `Tagged`.`contact_id`
FROM contacts_tags AS Tagged LEFT JOIN tags AS Tag ON (`Tagged`.`tag_id` = `Tag`.`id`)
WHERE `Tag`.`id` = 137 );
这会一直运行,直到我重置服务器。
但是当我手动列出第一个查询响应时它就起作用了:
SELECT `Contact`.*
FROM `contacts` AS `Contact`
WHERE `Contact`.`id` in
(3519, 17080);
有什么区别?
When I isolate this query:
SELECT `Tagged`.`contact_id`
FROM contacts_tags AS Tagged LEFT JOIN tags AS Tag ON (`Tagged`.`tag_id` = `Tag`.`id`)
WHERE `Tag`.`id` = 137;
i get:
+------------+
| contact_id |
+------------+
| 3519 |
| 17080 |
+------------+
But when i combine it with a larger query using "IN" I get some sort of recursive loop and my database starts eating up processing power until it times out.
SELECT `Contact`.*
FROM `contacts` AS `Contact`
WHERE `Contact`.`id` in
(SELECT `Tagged`.`contact_id`
FROM contacts_tags AS Tagged LEFT JOIN tags AS Tag ON (`Tagged`.`tag_id` = `Tag`.`id`)
WHERE `Tag`.`id` = 137 );
This just keeps running until i reset the server.
But then It works when I list the first query response manually:
SELECT `Contact`.*
FROM `contacts` AS `Contact`
WHERE `Contact`.`id` in
(3519, 17080);
What is the difference?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
MySQL 当前的 GA 版本在优化子查询方面确实很糟糕。有可能正在针对
Contacts
中的每一行执行子查询。如果您运行EXPLAIN your_query_here
,您就可以看到这一点。您会看到子查询已被标记为DEPENDENT SUBQUERY
。这不是一个很好的解决方案,但类似的东西可能会起作用。
这应该强制 MySQL 缓存子查询。或者,如果您知道查询将返回少量值,那么最好只执行两个单独的查询。
The current GA release of MySQL is really bad at optimizing subequeries. Chances are that the subquery is being executed for each row in
Contacts
. You can see this if you runEXPLAIN your_query_here
. You'll like see that the subquery has been taggedDEPENDENT SUBQUERY
.It's not a great solution, but something like this might work.
This should force MySQL to cache the subquery. Alternatively, if you know that query is going to return a small number of values, you might be better off simply performing two separate queries.
如果查看子查询
,则它不会不限制
contact_tags
:删除LEFT
进行限制(等连接)。重写后看起来像:
或
这很奇怪。看起来缺少某些条件。
If one looks at the subquery
Then it does not restrict
contact_tags
: deleteLEFT
for a restriction (equi-join).Rewritten it looks like:
or
Which is just weird. It looks like some condition is missing.