问题 左连接更快或内连接更快?


那么......哪一个更快(NULl值不是问题),并被索引。

SELECT * FROM A
  JOIN B b ON b.id = a.id
  JOIN C c ON c.id = b.id 
 WHERE A.id = '12345'

使用左连接:

SELECT * FROM A
 LEFT JOIN B ON B.id=A.bid
 LEFT JOIN C ON C.id=B.cid
WHERE A.id = '12345'

这是实际的查询 这是......两者都返回相同的结果

Query (0.2693sec) :
    EXPLAIN EXTENDED SELECT * 
    FROM friend_events, zcms_users, user_events, 
    EVENTS WHERE friend_events.userid = '13006'
    AND friend_events.state =0
    AND UNIX_TIMESTAMP( friend_events.t ) >=1258923485
    AND friend_events.xid = user_events.id
    AND user_events.eid = events.eid
    AND events.active =1
    AND zcms_users.id = user_events.userid

EXPLAIN

    id select_type table type possible_keys key key_len ref rows Extra 
    1 SIMPLE zcms_users ALL PRIMARY NULL NULL NULL 43082 
    1 SIMPLE user_events ref PRIMARY,eid,userid userid 4 zcms_users.id 1 
    1 SIMPLE events eq_ref PRIMARY,active PRIMARY4 user_events.eid 1 Using where
    1 SIMPLE friend_events eq_ref PRIMARY PRIMARY 8 user_events.id,const 1 Using where



    LEFTJOIN QUERY: (0.0393 sec)

    EXPLAIN EXTENDED SELECT * 
    FROM `friend_events` 
    LEFT JOIN `user_events` ON user_events.id = friend_events.xid
    LEFT JOIN `events` ON user_events.eid = events.eid
    LEFT JOIN `zcms_users` ON user_events.userid = zcms_users.id
    WHERE (
    events.active =1
    )
    AND (
    friend_events.userid = '13006'
    )
    AND (
    friend_events.state =0
    )
    AND (
    UNIX_TIMESTAMP( friend_events.t ) >=1258923485
    )


EXPLAIN
    id select_type table type possible_keys key key_len ref rows Extra 
    1 SIMPLE friend_events ALL PRIMARY NULL NULL NULL 53113 Using where
    1 SIMPLE user_events eq_ref PRIMARY,eid PRIMARY 4 friend_events.xid 1 Using where
    1 SIMPLE zcms_users eq_ref PRIMARY PRIMARY 4 user_events.userid 1 
    1 SIMPLE events eq_ref PRIMARY,active PRIMARY 4 user_events.eid 1 Using where

3548
2017-11-27 20:05


起源

你为什么不运行它们并告诉我们哪个更快? - Welbog
这个问题应该改写一下,“我怎样才能找出哪个查询运行得更快?” - Nathan Koop
这些事件会返回相同的结果吗? (列,而不是行) - JMD
@JMD我不明白为什么他们会返回不同的列。相反,它们很可能会返回不同的行。 - Nathan Koop
@Nathan:LEFT JOIN示例将返回A中的行,其中B和/或C中没有行--B / C列将为null。因此,LEFT JOIN结果集中有更多列。 - OMG Ponies


答案:


这取决于;跑他们两个找出来;然后运行'解释选择'来解释。

实际性能差异可以从“几乎不存在”到“非常重要”,具体取决于A中id ='12345'的行数在B和C中没有匹配记录。

更新 (根据发布的查询计划)

当你使用INNER JOIN时,从哪个表开始并不重要(结果方面,而不是性能方面),因此优化器会尝试选择它认为最佳的表。您似乎在所有适当的PK / FK列上都有索引,并且您要么没有索引 friend_events.userid 或者记录太多了 userid = '13006' 它没有被使用;无论哪种方式优化器选择具有较少行的表作为“基础” - 在这种情况下它是 zcms_users

当你使用LEFT JOIN时  事情(结果明智)从哪个表开始;从而 friend_events 被挑选。现在 为什么 这种方式花费的时间我不太确定;我正在猜测 friend_events.userid 条件有帮助。如果要在其上添加索引(实际上是varchar,btw?不是数字?),那么INNER JOIN也可能表现不同(并且变得更快)。


9
2017-11-27 20:08



我跑了。似乎内在的一点慢。但是不是内心应该更好地与左联合? - Murvinlai
你能为两个查询发布“解释选择”的结果吗? - ChssPly76


INNER JOIN必须进行额外检查以从A中删除任何在B和C中没有匹配记录的记录。根据最初从A返回的记录数量,它可能会产生影响。


3
2017-11-27 20:16





使用 说明 查看查询计划。对于这两种情况,它可能是相同的计划,所以我怀疑它有很大的不同,假设没有不匹配的行。但这些是两个不同的查询,所以比较它们真的没有意义 - 你应该只使用正确的查询。

为什么不使用“INNER JOIN”关键字而不是“LEFT JOIN”?


2
2017-11-27 20:09





LEFT JOIN 显示来自的所有数据 A 并且只显示来自的数据 B/C 只有条件成立。至于 INNER JOIN,它必须对两者做一些额外的检查 tables。所以,我猜这就解释了原因 LEFT JOIN 是比较快的。


1
2018-03-05 05:25