Подтвердить что ты не робот

Левый JOIN быстрее или Inner Join быстрее?

Итак... какой из них быстрее (значение 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
4b9b3361

Ответ 1

Это зависит; запустите их обоих, чтобы узнать; затем запустите объяснение для объяснения.

Фактическая разница в производительности может варьироваться от "практически несуществующей" до "довольно значительной" в зависимости от того, сколько строк в с id = '12345' не имеют совпадающих записей в B и C.

Обновить (на основе опубликованных планов запросов)

Когда вы используете INNER JOIN, это не имеет значения (по результатам, а не по производительности), с которой следует начинать таблицу, поэтому оптимизатор пытается выбрать тот, который, по его мнению, будет работать лучше всего. Кажется, у вас есть индексы во всех соответствующих столбцах PK/FK, и у вас либо нет индекса на friend_events.userid, либо слишком много записей с userid = '13006', и оно не используется; в любом случае оптимизатор выбирает таблицу с меньшим количеством строк в качестве "базы" - в этом случае она zcms_users.

Когда вы используете LEFT JOIN, это делает вопрос (по результатам), с какой таблицы следует начинать; таким образом, friend_events. Теперь почему это занимает меньше времени, поэтому я не совсем уверен; Я предполагаю, что условие friend_events.userid помогает. Если бы вы добавили индекс (действительно ли это varchar, btw? Not numeric?), То ваш INNER JOIN может вести себя по-другому (и быстрее).

Ответ 2

INNER JOIN должен выполнить дополнительную проверку, чтобы удалить любые записи из A, которые не имеют соответствующих записей в B и C. В зависимости от количества записей, первоначально возвращенных из A, это МОЖЕТ оказать влияние.

Ответ 3

Используйте EXPLAIN, чтобы увидеть план запроса. Вероятно, это один и тот же план для обоих случаев, поэтому я сомневаюсь, что это имеет большое значение, если нет строк, которые не совпадают. Но это два разных запроса, поэтому на самом деле не имеет смысла сравнивать их - вы должны просто использовать правильный.

Почему бы не использовать ключевое слово "INNER JOIN" вместо "LEFT JOIN"?

Ответ 4

LEFT JOIN отображает все данные из A и отображает только данные из B/C, только если условие истинно. Что касается INNER JOIN, он должен выполнить некоторую дополнительную проверку как на tables. Итак, я думаю, это объясняет, почему LEFT JOIN работает быстрее.