MySQL(版本5.5):为什么`JOIN`比`IN`子句更快?

时间:2014-09-02 13:25:34

标签: mysql sql join

[问题摘要:2个SQL语句产生相同的结果,但速度不同。一个语句使用JOIN,其他语句使用INJOININ]

我在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分钟。

为什么JOININ子句快得多?

3 个答案:

答案 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
  )