【问题标题】:Are subqueries cached by MySQL when used in a WHERE clause?在 WHERE 子句中使用时,子查询是否被 MySQL 缓存?
【发布时间】:2025-12-21 00:30:15
【问题描述】:

在以下查询中:

SELECT column_a, column_b FROM table_a WHERE
    column_b IN (SELECT b_id FROM table_b)

子查询 SELECT b_id FROM table_b 是否由 SQL 解析器缓存,或者提前执行查询是否会更快,将其保存为变量(例如在 PHP 中),然后将这些值作为 CSV 字符串传递?

例如

SELECT column_a, column_b FROM table_a WHERE
    column_b IN (1,3,4,6,8,10,16,18)

【问题讨论】:

  • IN 与子查询一起使用是一个糟糕的主意。您最好通过连接在此处获得所需的结果,因为查询本质上是等连接。 SELECT column_a, column_b FROM table_a JOIN table_b ON column_b = b_id
  • @TimSeguine:为什么这是一个糟糕的主意?如果table_b 是一个N:M 关系表,那么如果使用JOIN,则会从table_a 获得多行。这可能是不需要的。
  • @naitsirch 这是一个坏主意,因为 MySQL 对依赖子查询的支持很差。如果你能以任何方式避免它们,你可能应该这样做。一个精心挑选的GROUP BY 可以在大多数情况下消除无关结果。
  • 我们在问题中没有依赖(我认为您的意思是 correlated)子查询(有关相关子查询的解释,请参阅 here)。据我所知,这个查询应该和JOIN 一样高效,因为它只能执行一次。
  • @naitsirch 你是对的,它不相关。尽管如此,旧版本的 MySQL 有时会非常糟糕地优化 IN 子查询(评估外部表的每一行的整个子查询,在这种情况下是 a)。当我说老时,我的意思是到 5.5。如果可能,使用JOIN 重写通常是一个非常好的主意。

标签: mysql sql sql-server database optimization


【解决方案1】:

研究使用EXPLAIN EXTENDED 来充分说明对子查询的影响。

例如:

EXPLAIN EXTENDED
SELECT column_a, column_b FROM table_a WHERE
    column_b IN (SELECT b_id FROM table_b)

如果它们没有产生您希望的缓存结果,您可能有兴趣将它们存储在内存中(memcacheredis)、文件中(使用PHP file libraries)或单独的 SQL 缓存本身。

【讨论】:

  • @ypercubeᵀᴹ 以及任何支持它的人,您能解释一下或提供替代答案吗?