在 mysql 查询中的 SELECT 中使用 SELECT

Posted

技术标签:

【中文标题】在 mysql 查询中的 SELECT 中使用 SELECT【英文标题】:Using SELECT within SELECT in mysql query 【发布时间】:2012-01-25 00:22:07 【问题描述】:

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-4 秒;锁定时间大约 0.000090 秒;检查大约 200 行”的慢查询。

如果我拆分SELECT 查询,每个查询都会很快;但是这样会增加不擅长高并发的查询。

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

【问题讨论】:

SELECTSELECT 内?!这就像那部电影......选择。 【参考方案1】:

在 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 你应该重构,这些速度非常慢。

【讨论】:

【参考方案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')

只要确保你只选择你需要的,不要使用 *;还要说明您在哪个表中有标签列,以便您可以替换

【讨论】:

这就是我们所说的JOIN 是的,内连接两次,至少我认为它比 in 子句快【参考方案3】:

Join 过滤结果。第一次加入将保持满足第一个 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

【讨论】:

以上是关于在 mysql 查询中的 SELECT 中使用 SELECT的主要内容,如果未能解决你的问题,请参考以下文章

mysql 从动态表名中查询数据

MYSQL 存储函数中的 SELECT 查询

MySQL 指定查询中的每一列,而不是使用 SELECT * [重复]

PHP MySQL Select 之Select

python中的mysql数据库like模糊查询

MySQL中SELECT查询中的值分配和使用IF-ELSE