[问题摘要:2个SQL语句产生相同的结果,但速度不同。一个语句使用JOIN
,其他语句使用IN
。 JOIN
比IN
]
我在2个表上尝试了两种SELECT
语句,名为 booking_record 和包含。表包含与表 booking_record 具有多对一关系。
(为简单起见,不包括表格定义。)
第一句话:(使用IN
子句)
SELECT
id,
agent,
source
FROM
booking_record
WHERE
id IN
( SELECT DISTINCT
foreign_key_booking_record
FROM
inclusions
WHERE
foreign_key_bill IS NULL
AND
invoice_closure <> FALSE
)
第二句话:(使用JOIN
)
SELECT
id,
agent,
source
FROM
booking_record
JOIN
( SELECT DISTINCT
foreign_key_booking_record
FROM
inclusions
WHERE
foreign_key_bill IS NULL
AND
invoice_closure <> FALSE
) inclusions
ON
id = foreign_key_booking_record
在 booking_record -table中有300,000多行,在包含 -table中有6,100,000多行;第二个语句在0.08秒内发送了127行,但是第一个语句在相同的记录中花费了将近21分钟。
为什么JOIN
比IN
子句快得多?
答案 0 :(得分:2)
此行为已有详细记录。请参阅here。
简短的回答是,在MySQL版本5.6.6之前,MySQL在优化这些类型的查询方面表现不佳。会发生什么是每次为外部查询中的每一行运行子查询。大量的开销,一遍又一遍地运行相同的查询。您可以通过使用良好的索引并从distinct
子查询中删除in
来改善这一点。
如果您关心效果,这是我更喜欢exists
而不是in
的原因之一。
答案 1 :(得分:1)
EXPLAIN应该为您提供一些线索(Mysql Explain Syntax
我怀疑IN版本正在构建一个列表,然后由每个项目扫描(IN通常被认为是非常低效的构造,如果我有一个简短的项目列表可以手动输入,我只会使用它。)
JOIN更有可能为结果构建临时表,使其更像表之间的正常JOIN。
答案 2 :(得分:1)
你应该使用EXPLAIN来探索这个,正如Ollie所说。
但事先请注意,第二个命令还有一个过滤器:id = foreign_key_booking_record
。
检查这是否具有相同的性能:
SELECT
id,
agent,
source
FROM
booking_record
WHERE
id IN
( SELECT DISTINCT
foreign_key_booking_record
FROM
inclusions
WHERE
id = foreign_key_booking_record -- new filter
AND
foreign_key_bill IS NULL
AND
invoice_closure <> FALSE
)