在mysql查询中使用SELECT中的SELECT

时间:2011-12-21 05:49:16

标签: mysql sql database select

通常在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个查询,那么每个查询都会非常快;但这会增加不兼容高并发性的查询数量。

这是通常的情况,还是我的编码有问题?

3 个答案:

答案 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');

您可以在堆栈溢出上看到这些讨论:

question1 question2

加入有助于降低时间复杂度并提高服务器的稳定性。

将子查询转换为连接的信息:

link1 link2 link3