Я занимаюсь профилированием некоторых запросов в приложении, над которым я работаю, и натолкнулся на запрос, который извлекал больше строк, чем необходимо, и набор результатов был обрезан в коде приложения.
Изменение LEFT JOIN в INNER JOIN подрезало результирующий набор только тем, что было необходимо, и, по-видимому, также было бы более результативным (поскольку выбрано меньшее количество строк). В действительности, запрос LEFT JOIN's превосходил INNER JOIN'ed, в течение половины времени для завершения.
LEFT JOIN: (127 полных строк, запрос занял 0,0011 сек)
INNER JOIN: (10 полных строк, запрос занял 0,0024 сек)
(Я запускал запросы несколько раз, и это средние значения).
Запуск EXPLAIN на обоих не показывает ничего, что объясняет различия в производительности:
Для INNER JOIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE contacts index NULL name 302 NULL 235 Using where
1 SIMPLE lists eq_ref PRIMARY PRIMARY 4 contacts.list_id 1
1 SIMPLE lists_to_users eq_ref PRIMARY PRIMARY 8 lists.id,const 1
1 SIMPLE tags eq_ref PRIMARY PRIMARY 4 lists_to_users.tag_id 1
1 SIMPLE users eq_ref email_2 email_2 302 contacts.email 1 Using where
Для LEFT JOIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE contacts index NULL name 302 NULL 235 Using where
1 SIMPLE lists eq_ref PRIMARY PRIMARY 4 contacts.list_id 1
1 SIMPLE lists_to_users eq_ref PRIMARY PRIMARY 8 lists.id,const 1
1 SIMPLE tags eq_ref PRIMARY PRIMARY 4 lists_to_users.tag_id 1
1 SIMPLE users eq_ref email_2 email_2 302 contacts.email 1
И сам запрос:
SELECT `contacts`.*, `lists`.`name` AS `group`, `lists`.`id` AS `group_id`, `lists`.`shared_yn`, `tags`.`name` AS `context`, `tags`.`id` AS `context_id`, `tags`.`color` AS `context_color`, `users`.`id` AS `user_id`, `users`.`avatar`
FROM `contacts`
LEFT JOIN `lists` ON lists.id=contacts.list_id
LEFT JOIN `lists_to_users` ON lists_to_users.list_id=lists.id AND lists_to_users.user_id='1' AND lists_to_users.creator='1'
LEFT JOIN `tags` ON tags.id=lists_to_users.tag_id
INNER JOIN `users` ON users.email=contacts.email
WHERE (contacts.user_id='1')
ORDER BY `contacts`.`name` ASC
(Предложение, о котором я говорю, это последний INNER JOIN в таблице "users" )
Запрос выполняется в базе данных MySQL 5.1, если это имеет значение.
Кто-нибудь знает, почему LEFT JOIN'ed запрос превосходит INNER JOIN'ed в этом случае?
ОБНОВЛЕНИЕ: Из-за предложения Томалака, что небольшие таблицы, которые я использую, делали INNER JOIN более сложными, я создал тестовую базу данных с некоторыми макетными данными. Таблица "пользователей" - 5000 строк, а таблица контактов - 500 000 строк. Результаты одинаковы (также тайминги не изменились, что удивительно, если учесть, что таблицы теперь намного больше).
Я также использовал ANALYZE и OPTIMIZE в таблице контактов. Не было различимых различий.