2013-01-14 169 views
0

設置

我正在創建一個活動列表,其中用戶可以通過多個過濾器縮小結果範圍。而不是具有表中的每個濾波器(即EVENT_CATEGORY,event_price)我有以下的數據庫結構(以方便/靈活添加後更多的過濾器):基於複合表中相關記錄的查詢選擇記錄的效率

事件

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

fllter

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

filter_item

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)。

的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()與子查詢和這些子查詢執行多個連接的問題?這個查詢非常快,只有數據庫中的幾條記錄,但是當數以千計或數以萬計的時候呢?

任何指導真的很感激!

最佳,

克里斯

回答

0

雖然EXISTS只是一種連接形式,MySQL查詢優化器是出了名的"stupid"關於最佳執行它。就你而言,它可能會對外表執行全表掃描,然後對每行執行相關子查詢,這必然會嚴重縮小。出於這個原因,人們經常將EXISTS重寫爲明確的JOIN。或者,只需使用更智能的DBMS。

除此之外,考慮使用filter_item的複合PK,其中FK處於最前沿 - InnoDB tables are clustered,並且您希望將屬於同一個過濾器的項目物理上靠近在一起。

順便說一句,成千上萬的行數不是「大」 - 要真正測試數千萬甚至更多的可伸縮性。

+0

感謝您的信息。我不知道mysql是否愚蠢...(這兩個版本是相同的,正如你可能知道的)BTW:Innodb是否對此表示贊同? – wildplasser

+0

@wildplasser我不相信。 –