使用MySQL“in”导致循环?

发布于 2025-01-03 03:01:26 字数 810 浏览 2 评论 0原文

当我隔离这个查询时:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

筱武穆 2025-01-10 03:01:26

MySQL 当前的 GA 版本在优化子查询方面确实很糟糕。有可能正在针对 Contacts 中的每一行执行子查询。如果您运行EXPLAIN your_query_here,您就可以看到这一点。您会看到子查询已被标记为DEPENDENT SUBQUERY

这不是一个很好的解决方案,但类似的东西可能会起作用。

"SELECT `Contact`.*
FROM `contacts` AS `Contact` 
WHERE `Contact`.`id` in 
(SELECT * FROM (SELECT `Tagged`.`contact_id` 
FROM contacts_tags AS Tagged LEFT JOIN tags AS Tag ON (`Tagged`.`tag_id` = `Tag`.`id`)  
WHERE `Tag`.`id` = 137 ) x);"

这应该强制 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 run EXPLAIN your_query_here. You'll like see that the subquery has been tagged DEPENDENT SUBQUERY.

It's not a great solution, but something like this might work.

"SELECT `Contact`.*
FROM `contacts` AS `Contact` 
WHERE `Contact`.`id` in 
(SELECT * FROM (SELECT `Tagged`.`contact_id` 
FROM contacts_tags AS Tagged LEFT JOIN tags AS Tag ON (`Tagged`.`tag_id` = `Tag`.`id`)  
WHERE `Tag`.`id` = 137 ) x);"

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.

雅心素梦 2025-01-10 03:01:26

如果查看子查询

SELECT ct.contact_id 
FROM contacts_tags AS ct
LEFT JOIN tags AS t ON ct.tag_id = t.id  

,则它不会不限制 contact_tags:删除LEFT 进行限制(等连接)。

重写后看起来像:

SELECT DISTINCT c.*
FROM contacts AS c
JOIN tags AS t ON  c.id = t.contact_id
JOIN contacts_tags AS ct ON ct.tag_id = t.id
WHERE
    t.id = 137

SELECT c.*
FROM contacts AS c
JOIN tags AS t ON  c.id = t.contact_id
WHERE
    t.id = 137
AND
    EXISTS(SELECT *
    FROM contacts_tags AS ct
    WHERE ct.tag_id = 137)

这很奇怪。看起来缺少某些条件。

If one looks at the subquery

SELECT ct.contact_id 
FROM contacts_tags AS ct
LEFT JOIN tags AS t ON ct.tag_id = t.id  

Then it does not restrict contact_tags: delete LEFT for a restriction (equi-join).

Rewritten it looks like:

SELECT DISTINCT c.*
FROM contacts AS c
JOIN tags AS t ON  c.id = t.contact_id
JOIN contacts_tags AS ct ON ct.tag_id = t.id
WHERE
    t.id = 137

or

SELECT c.*
FROM contacts AS c
JOIN tags AS t ON  c.id = t.contact_id
WHERE
    t.id = 137
AND
    EXISTS(SELECT *
    FROM contacts_tags AS ct
    WHERE ct.tag_id = 137)

Which is just weird. It looks like some condition is missing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文