Я профилировал некоторые запросы в приложении, над которым я работаю, и натолкнулся на запрос, который извлекал больше строк, чем необходимо, а результирующий набор был урезан в коде приложения.
Изменение ЛЕВОГО СОЕДИНЕНИЯ на ВНУТРЕННЕЕ СОЕДИНЕНИЕ обрезало результирующий набор до того, что было необходимо, и, вероятно, также было бы более производительным (так как выбрано меньше строк). На самом деле, запрос LEFT JOIN превосходил INNER JOIN, занимая половину времени.
LEFT JOIN: (всего 127 строк, запрос занял 0,0011 с)
ВНУТРЕННЕЕ СОЕДИНЕНИЕ: (всего 10 строк, запрос занял 0,0024 с)
(я выполнял запросы несколько раз, и это средние значения).
Запуск EXPLAIN на обоих не показывает ничего, что объясняет различия в производительности:
ДЛЯ ВНУТРЕННЕГО СОЕДИНЕНИЯ:
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
Для левого соединения:
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 превосходит INNER JOIN в этом случае?
ОБНОВЛЕНИЕ: Из-за предположения Томалака, что маленькие таблицы, которые я использую, усложняли INNER JOIN, я создал тестовую базу данных с некоторыми фиктивными данными. Таблица 'users' содержит 5000 строк, а таблица контактов ~ 500 000 строк. Результаты одинаковы (также время не изменилось, что удивительно, если учесть, что таблицы теперь намного больше).
Я также запустил ANALYZE и OPTIMIZE в таблице контактов. Ничего не заметно.