【问题标题】:Mysql long subquery "in" issueMysql 长子查询“in”问题
【发布时间】:2026-01-19 08:05:01
【问题描述】:

我无法理解简单 MySQL 查询中的问题。请看这里

select SQL_NO_CACHE
    ID,
    post_title,
    post_type
from wp_posts 
where 1
  and (wp_posts.ID in (select id from ...[complex subquery here]...))

这个查询运行时间很长(2.5 秒),但如果我单独运行子查询(从“in (..”) 开始的查询只需要 0.15 秒。子查询只返回 60 行,我认为整个查询已经在这种情况下跑得更快。

顺便说一句,我尝试使用固定 ID 列表而不是子查询来运行整个查询,例如

select SQL_NO_CACHE
    ID,
    post_title,
    post_type
from wp_posts 
where 1
and (wp_posts.ID in
(
48393,
52796, .... 58 more numbers))

而且它的工作速度非常快(约 1 毫秒)。

哪里出了问题?为什么整个查询运行如此缓慢,我该如何改进?谢谢。

【问题讨论】:

  • 根据子查询,MySQL 可能认为它是一个“相关”子查询,并重复运行它,对 wp_posts 中的每一行运行一次。我有时会发现INNER JOINing 这样的子查询更快;如果失败了,只需将子查询结果放入 TEMPORARY 表中,然后加入。

标签: mysql optimization query-optimization


【解决方案1】:

如上所述,mysql 在这种情况下并不擅长优化查询。可能发生的是它对 wp_posts 中的每条记录执行一次子查询。通过将它们组合成一个带有连接的查询来避免这种行为

select SQL_NO_CACHE
    ID,
    post_title,
    post_type
from wp_posts
left join another_table on wp_posts.id = another_table.post_id
where {complex conditions from your other query}

希望对你有帮助

【讨论】:

  • 谢谢。我认为这会有所帮助,但是我不能在主查询中使用左连接,这是我的任务的限制。我只能将子查询放在主子查询的“WHERE”块中。我已经尝试在子查询上方再添加一个“来自”,但这没有帮助。
  • 我在子查询中有一个“like”运算符,这就是它在没有索引的情况下运行的原因,我在 EXPLAIN 中看到它,但是我无法删除此运算符,我认为我无法为其添加索引.正如我之前所说,我的子查询运行时间为 0.15 秒,这对我有好处。我正在等待整个查询约 0.2 秒,这是我需要达到的目标。
  • 这是结构的问题。如果 ID 没有被索引,那么它将为 wp_posts 中的每一行运行一次子查询。因此,如果您的子查询以 0.15 秒运行,但 wp_posts 中有 100 条记录,那么总数将为 15 秒。如果有 10000 条记录,那么这将成为一个大问题。要么确保 ID 在两个表中都有索引(如果可以,将它们作为外键链接),或者你需要放弃以这种方式使用子查询的想法。
  • 谢谢,您指的是哪个 ID?当然,在源表中,所有 ID 都会被索引。唯一没有索引的地方是子查询中的“LIKE '%..%'”运算符(与ID无关,而是用于搜索其他表列中的某些子字符串)。
  • LIKE %..% 是出了名的慢。这就是为什么它需要 0.15 秒而不是 0.00015 秒的原因。如果您可以使用它,那么即使子查询被加载数千次,它仍然会很快。我们可以查看子查询以便我或其他人找到解决方法吗?
【解决方案2】:

您的数字实际上是一个未编入索引的表格。 通过explain 运行您的查询并见证tablescan 的困境。

下面可以解释一个执行计划:

http://www.sitepoint.com/using-explain-to-write-better-mysql-queries/

【讨论】:

    【解决方案3】:

    谢谢大家,我已经重建了一个查询并使用了“内连接”方式。用我最初计划的想法似乎没有好的方法来解决它。

    【讨论】: