Допустим, у вас есть 5 таблиц, каждый из которых имеет столбцы:
- дом (id, name, street_id)
- street (id, name)
- photo(идентификатор, имя)
- house_photo (house_id, photo_id)
- street_photo (street_id, photo_id)
И произнесите все столбцы «id» и столбец, заканчивающийся на «У _id 'уже есть индексы.
(На самом деле мой запрос не имеет ничего общего с домами или улицами. Они ради аргументов.)
Теперь скажем, что вы хотели бы получить каждую улицу вколонке, и если на этой улице или в ее домах есть фотографии, вам нужны фотографии в следующей колонке ...
Хитрость здесь заключается в том, что все дома находятся в одной таблице.И все фото в другой таблице.Но чтобы связать 2, нам нужно получить доступ ко всем пяти таблицам.
Я пришел к следующему запросу, содержащему 4 JOIN:
SELECT
street.name
,group_concat(distinct photos.name SEPARATOR '\n') as photos
FROM
house
INNER JOIN street ON
house.street_id = street.id
LEFT JOIN house_photos ON
house.id = house_photos.house_id
LEFT JOIN street_photos ON
street.id = street_photos.street_id
LEFT JOIN photos ON
photos.id = house_photos.photo_id
OR photos.id = street_photos.photo_id
GROUP BY
street.name
Различное, чтобы отфильтровать двойные числа,поскольку они будут сгенерированы, когда у вас есть более 1 фотография для дома и более 1 фотография для улицы этого дома.(Carthesian product) Но это не имеет никакого отношения к моей проблеме.
Проблема, с которой я столкнулся, заключается в том, что запрос СУПЕР медленный.(Более 1 минуты или даже больше, чтобы закончить)
Когда я прошу MySQL проанализировать запрос («объяснить расширенный»), я вижу, что он не будет использовать доступные индексы при обработке этого последнего JOIN (которыйв операторе ON указано ИЛИ).
Если я разделю последнее СОЕДИНЕНИЕ на 2 СОЕДИНЕНИЯ (добавив, таким образом, пятое СОЕДИНЕНИЕ), запрос снова станет очень быстрым (для завершения потребуется доля секунды).
SELECT
street.name
,concat(
group_concat(distinct photos_from_house.name SEPARATOR '\n')
,'\n'
,group_concat(distinct photos_from_street.name SEPARATOR '\n')
) as photos
FROM
house
INNER JOIN street ON
house.street_id = street.id
LEFT JOIN house_photos ON
house.id = house_photos.house_id
LEFT JOIN street_photos ON
street.id = street_photos.street_id
LEFT JOIN photos photos_from_house ON
photos_from_house.id = house_photos.photo_id
LEFT JOIN photos photos_from_street ON
photos_from_street.id = street_photos.photo_id
GROUP BY
street.name
Мой вопрос теперь таков: почему вводится OR в предложении ON, а MySQL не использует доступные индексы / ключи для этого JOIN?
Я уже УЖЕ попытался использовать USE INDEX иИНДЕКС СИЛЫ, но он не сдвинется с места.
Любые объяснения / помощь приветствуются.