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

場合によります; 両方を実行して確認してください。次に、説明のために「explain select」を実行します。

実際のパフォーマンスの違いは、B と C に一致するレコードがない id='12345' の A の行数に応じて、「実質的に存在しない」から「かなり重要」に及ぶ場合があります。

更新(投稿されたクエリ プランに基づく)

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 は、B と C に一致するレコードがない A からのレコードを削除するために、追加のチェックを行う必要があります。A から最初に返されたレコードの数によっては、影響がある可能性があります。

于 2009-11-27T20:16:51.837 に答える
2

LEFT JOINからのすべてのデータを表示し、条件が true の場合のみAからのデータのみを表示します。B/CについてINNER JOINは、両方で追加のチェックを行う必要がありtablesます。LEFT JOINだから、それがなぜ速いのかを説明していると思います。

于 2015-03-05T05:25:17.173 に答える
2

EXPLAINを使用してクエリ プランを表示します。どちらの場合もおそらく同じ計画なので、一致しない行がないと仮定すると、大きな違いがあるとは思えません。しかし、これらは 2 つの異なるクエリであるため、それらを比較する意味はありません。正しい方を使用する必要があります。

「LEFT JOIN」の代わりに「INNER JOIN」キーワードを使用しないのはなぜですか?

于 2009-11-27T20:09:54.037 に答える