3

それぞれの列を持つ 5 つのテーブルがあるとします。

  • 家 (id、名前、street_id)
  • 通り(ID、名前)
  • 写真(ID、名前)
  • house_photo (house_id、photo_id)
  • street_photo (street_id、photo_id)

そして、すべての「id」列と「_id」で終わる列には既にインデックスがあるとします。

(実際、私の質問は家や通りとは何の関係もありません。それらは議論のためです。)

ここで、各通りを列に入れたいとします。その通りまたはその家に写真がある場合は、次の列に写真を入れたいとします...

ここで注意が必要なのは、すべての家が 1 つのテーブルにあることです。そして、別のテーブルのすべての写真。しかし、2 つをリンクするには、5 つのテーブルすべてにアクセスする必要があります。

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 枚以上ある場合に二重が生成されるため、重複を除外することが明確です。(カルテジアン製品)しかし、これは私の問題とは何の関係もありません。

私が抱えている問題は、クエリが非常に遅いことです。(終了まで1分以上かかります)

MySQL にクエリを分析するように依頼すると ('explain extended')、最後の JOIN (ON 句に OR がある) を処理するときに使用可能なインデックスが使用されないことがわかります。

最後の JOIN を 2 つの JOIN に分割すると (つまり、5 番目の JOIN を追加する)、クエリは再び非常に高速になります (完了するのに 1 秒かかります)。

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 を使用してみましたが、動きません。

説明/ヘルプは大歓迎です。

4

1 に答える 1