使用 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
当然还有正确索引所有相关字段。
我刚刚发现我的应用程序中的一个页面加载非常慢,因为某个 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
当然还有正确索引所有相关字段。