使用 SELECT 子查询优化 SELECT IN () SQL 查询 returns 多行

Optimizing SELECT IN () SQL query with SELECT subquery that returns many rows

我刚刚发现我的应用程序中的一个页面加载非常慢,因为某个 SQL 查询,其中有很多。

我已阅读 this document about subquery optimization 但它似乎概述了 MySQL 如何优化子查询,而不是我如何优化我的查询。我确实尝试了一些从文档中得到的想法,但无济于事。

这是目前我的慢速查询。为了便于阅读,我简化了 table 和列名:

SELECT
    a.one, a.two, a.three, a.four,
    b.*,
    a.id,
    b.id,
    c.one, c.id,
    d.one,
    f.one
FROM a
JOIN b ON a.id = b.a_id
JOIN c ON c.id = b.c_id
JOIN e ON b.e_id = e.id
JOIN d ON d.id = e.d_id
JOIN f ON f.id = b.f_id
WHERE a.id IN (
    SELECT a_id FROM b WHERE a_id IS NOT NULL AND g_id = 95
)

SELECT 子查询当前 returns 750 多行,我认为这会导致父查询延迟。整个查询耗时25秒。

如何优化此查询?

在 5.6.5 之前,MySQL 不会具体化子查询。这意味着对于连接上的每条记录,它将 运行 以下相关查询:

SELECT  1
FROM    b
WHERE   a_id IS NOT NULL
        AND g_id = 95
        /* optimizer added */
        AND a_id = a.id
LIMIT   1

,优化器添加了一个附加条件。

从 5.6.5 开始,MySQL 能够将 IN 子查询的结果具体化为一个临时的 table 并像任何其他查询一样加入它。

如果您使用的是 5.6.5 之前的 MySQL,您可以尝试将条件重写为连接:

SELECT  a.one, a.two, a.three, a.four,
        b.*,
        a.id,
        b.id,
        c.one, c.id,
        d.one,
        f.one
FROM    (
        SELECT  DISTINCT a_id
        FROM    b
        WHERE   a_id IS NOT NULL
                AND g_id = 95
        ) bi
JOIN a ON a.id = bi.a_id
JOIN b ON a.id = b.a_id
JOIN c ON c.id = b.c_id
JOIN e ON b.e_id = e.id
JOIN d ON d.id = e.d_id
JOIN f ON f.id = b.f_id

当然还有正确索引所有相关字段。