0

設定

ユーザーが複数のフィルターで結果を絞り込めるイベント リストを作成しています。各フィルター (つまり、event_category、event_price) のテーブルを用意するのではなく、次のデータベース構造を使用します (後でフィルターを簡単に/柔軟に追加できるようにするため):

イベント

event_id    title    description   [etc...]
-------------------------------------------

ちらつく

filter_id    name        slug
-----------------------------
1            Category    category
2            Price       price

フィルター項目

filter_item_id    filter_id   name          slug
------------------------------------------------
1                 1           Music         music
2                 1           Restaurant    restaurant
3                 2           High          high
4                 2           Low           low

event_filter_item

event_id    filter_item_id
--------------------------
1           1
1           4
2           1
2           3

ゴール

データベースにクエリを実行し、ユーザーが指定したフィルターを適用したいと考えています。たとえば、ユーザーが「音楽」(カテゴリ) で価格が「低」(価格) のイベントを検索した場合、(event_id = 1 の) 1 つのイベントのみが表示されます。

URL は次のようになります。

www.site.com/events?category=music&price=low

そのため、URL から受け取ったフィルター「スラッグ」を使用してデータベースにクエリを実行する必要があります。

これは、これを機能させるために私が書いたクエリです。

SELECT ev.* FROM event ev  
WHERE  
EXISTS (SELECT * FROM event_filter_item efi 
    JOIN filter_item fi on fi.filter_item_id = efi.filter_item_id
    JOIN filter f on f.filter_id = fi.filter_id 
    WHERE efi.event_id = ev.event_id AND f.slug = 'category' AND fi.slug ='music')
AND EXISTS (SELECT * FROM event_filter_item efi 
    JOIN filter_item fi on fi.filter_item_id = efi.filter_item_id
    JOIN filter f on f.filter_id = fi.filter_id 
    WHERE efi.event_id = ev.event_id AND f.slug = 'price' AND fi.slug = 'low')

このクエリは現在ハードコードされていますが、URL に存在するフィルターとスラッグに基づいて PHP で動的に生成されます。

そして大きな疑問は…

これはこれを行うための合理的な方法ですか?サブクエリで複数の EXISTS() を使用し、それらのサブクエリが複数の結合を実行することに問題がある人はいますか? このクエリは、データベースに数レコードしかない場合は非常に高速ですが、数千または数万のレコードがある場合はどうでしょうか?

どんなガイダンスも本当に感謝しています!

一番、

クリス

4

1 に答える 1

0

EXISTS は単なる JOIN の形式ですが、MySQL クエリ オプティマイザーはそれを最適に実行することに関して「愚か」であることで有名です。あなたの場合、おそらく外側のテーブルで完全なテーブルスキャンを実行し、次に各行に対して相関サブクエリを実行しますが、これはスケールが悪いことにバインドされています。そのため、EXISTS を明示的な JOIN として書き直すことがよくあります。または、よりスマートな DBMS を使用してください。

それに加えて、filter_itemFK が最前線にある に複合PK を使用することを検討してください。

ところで、数万は「大きな」行数ではありません。スケーラビリティを真にテストするには、数千万以上を使用します。

于 2013-01-14T22:45:04.567 に答える