通常在SELECT
中使用SELECT
来减少查询次数;但是当我检查这会导致查询速度变慢(这显然对mysql性能有害)。我有一个简单的查询
SELECT something
FROM posts
WHERE id IN (
SELECT tag_map.id
FROM tag_map
INNER JOIN tags
ON tags.tag_id=tag_map.tag_id
WHERE tag IN ('tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6')
)
这会导致“查询时间3-4s;锁定时间约为0.000090s;检查约200行”的查询速度慢。
如果我分割SELECT
个查询,那么每个查询都会非常快;但这会增加不兼容高并发性的查询数量。
这是通常的情况,还是我的编码有问题?
答案 0 :(得分:13)
在MySQL中,执行这样的子查询是“相关查询”。这意味着外部SELECT
的结果取决于内部SELECT
的结果。结果是你的内部查询每行执行一次,这非常慢。
你应该重构这个查询;您是否加入两次或使用两个查询大多无关紧要。加入两次会给你:
SELECT something
FROM posts
INNER JOIN tag_map ON tag_map.id = posts.id
INNER JOIN tags ON tags.tag_id = tag_map.tag_id
WHERE tags.tag IN ('tag1', ...)
有关详细信息,请参阅converting subqueries to JOINs上的MySQL手册。
提示:EXPLAIN SELECT
将向您展示优化程序如何计划处理您的查询。如果你看到DEPENDENT SUBQUERY
你应该重构,这些都是非常慢的。
答案 1 :(得分:2)
您可以使用以下方法改进它:
SELECT something
FROM posts
INNER JOIN tag_map ON tag_map.id = posts.id
INNER JOIN tags
ON tags.tag_id=tag_map.tag_id
WHERE <tablename>.tag IN ('tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6')
确保只选择你需要的东西,不要使用*;还说明您在哪个表中有标记列,以便替换&lt; tablename&gt;
答案 2 :(得分:1)
加入会对结果进行过滤。第一次连接将保持满足第一个ON条件的结果,然后第二个条件在第二个ON条件下给出最终结果。
SELECT something
FROM posts
INNER JOIN tag_map ON tag_map.id = posts.id
INNER JOIN tags ON tags.tag_id = tag_map.tag_id AND tags.tag IN ('tag1', 'tag2', 'tag3', 'tag4', 'tag5', 'tag6');
您可以在堆栈溢出上看到这些讨论:
加入有助于降低时间复杂度并提高服务器的稳定性。
将子查询转换为连接的信息: