假设您有 5 个表,每个表都有它们的列:
- 房子(id,name,street_id)
- 街道(ID,名称)
- 照片(身份证,姓名)
- 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 产品)但这与我的问题无关。
我遇到的问题是查询超级慢。(需要超过 1 分钟甚至更长的时间才能完成)
当我要求 MySQL 分析查询('explain extended')时,我看到它在处理最后一个 JOIN(在 ON 子句中有一个 OR)时不会使用可用的索引。
如果我将最后一个 JOIN 拆分为 2 个 JOIN,(从而添加第五个 JOIN),查询再次变得非常快。(需要一秒钟才能完成。)
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
我现在的问题是:为什么在 ON 子句中引入 OR,使 MySQL 不使用该 JOIN 的可用索引/键?
我已经尝试过使用 USE INDEX 和 FORCE INDEX,但它不会让步。
欢迎任何解释/帮助。