2014-09-02 54 views
0

[问题摘要:2个SQL语句产生相同的结果,但速度不同。一个声明使用JOIN,其他用途INJOIN快于IN]MySQL(版本5.5):为什么`JOIN`比`IN`子句快?

我尝试了2种SELECT声明对2个表,命名为 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 

与300,000行在 booking_record - 表和6,100,000+行内含物 -table;第二个声明在0.08秒内传递了127行,但第一个声明花费了将近21分钟的时间记录。

为什么JOININ子句快得多?

+4

我建议你开始使用'EXPLAIN'两个语句并查看结果来探讨这个问题。 – 2014-09-02 13:30:14

+0

第二个还有一个过滤器'id = foreign_key_booking_record'。 – 2014-09-02 13:33:13

+0

性能差异的最可能解释是生成的执行计划中的差异。正如其他答案已经表明的那样,'EXPLAIN'的输出将显示每个查询的执行计划。 IN(子查询)的一个重大性能问题:MySQL可能对外部查询返回的每一行执行子查询。 – spencer7593 2014-09-02 14:09:12

回答

2

此行为是详细记录。见here

简短的回答是,直到MySQL版本5.6.6,MySQL在优化这些类型的查询方面做得很差。会发生什么情况是,外部查询中的每一行都会运行子查询。很多开销,反复运行相同的查询。您可以通过使用良好的索引并从in子查询中删除distinct来改善此问题。

这是我更喜欢exists而不是in的原因之一,如果你关心性能。

1

EXPLAIN应该给你一些线索(Mysql Explain Syntax

我怀疑是版本正在建设一个名单,然后由每个项目扫描(IN被普遍认为是非常低效的结构,我只使用它,如果我有项目的短名单,手动输入)。

联接是更有可能建造一个临时表的结果,使得它更像是正常的表之间连接。

+0

Ollie打败我,解释它:P – Giles 2014-09-02 13:38:23

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 
)