Оставил JOIN быстрее или Inner Join быстрее? - PullRequest
11 голосов
/ 27 ноября 2009

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

9 голосов
/ 27 ноября 2009

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

Фактическая разница в производительности может варьироваться от «практически не существующей» до «довольно значительной» в зависимости от того, сколько строк в 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 может вести себя по-другому (и стать быстрее).

4 голосов
/ 27 ноября 2009

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

2 голосов
/ 27 ноября 2009

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

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

1 голос
/ 05 марта 2015

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...