13

所以......哪个更快(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
4

4 回答 4

9

这取决于; 运行它们以找出答案;然后运行“解释选择”以获得解释。

实际的性能差异可能从“几乎不存在”到“相当显着”,具体取决于 A 中有多少行 id='12345' 在 B 和 C 中没有匹配的记录。

更新(基于发布的查询计划)

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

当您使用 LEFT JOIN 时,从哪个表开始(结果方面)确实很重要;因此friend_events被选中。现在为什么我不太确定那样需要更少的时间;我猜friend_events.userid条件有帮助。如果您要在其上添加一个索引(它真的是 varchar,顺便说一句?不是数字?),您的 INNER JOIN 的行为也可能不同(并且变得更快)。

于 2009-11-27T20:08:40.680 回答
6

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

于 2009-11-27T20:16:51.837 回答
2

LEFT JOIN显示来自的所有数据,A并且仅B/C当条件为真时才显示来自的数据。至于INNER JOIN,它必须对两者进行一些额外的检查tables。所以,我想这解释了为什么LEFT JOIN更快。

于 2015-03-05T05:25:17.173 回答
2

使用EXPLAIN查看查询计划。这两种情况可能是相同的计划,所以我怀疑它是否有很大的不同,假设没有不匹配的行。但这是两个不同的查询,因此比较它们确实没有意义 - 您应该使用正确的查询。

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

于 2009-11-27T20:09:54.037 回答