2014-04-28 96 views
0

我正在查詢我的數據庫,以獲取教師的主要位置或教師提供的可用位置信息的位置列表。爲什麼兩個連接運行速度比OR條件快?

如果我做兩聯接這樣的:

SELECT tea.*, avail_loc.*, pri_loc.* 
FROM teachers AS tea 
    LEFT JOIN availability AS ava 
      ON(tea.teacher_id = ava.teacher_id AND ava.end_date > 1398706428) 
    LEFT JOIN locations AS avail_loc 
      ON(ava.location_id = avail_loc.location_id) 
    LEFT JOIN locations AS pri_loc 
      ON(tea.location_id = pri_loc.location_id) 
WHERE tea.active = 1 

我的查詢需要0.05秒。問題是我必須在php中清理輸出,因爲我的位置在avail_loc(備用位置)和pri_loc(主位置)之間分開。

因此,如果我將它們與OR條件組合成一個連接,查詢需要0.8秒。

SELECT tea.*, loc.* 
FROM teachers AS tea 
    LEFT JOIN availability AS ava 
      ON(tea.teacher_id = ava.teacher_id AND ava.end_date > 1398706428) 
    LEFT JOIN locations AS loc 
      ON(ava.location_id = loc.location_id OR tea.location_id = loc.location_id) 
WHERE tea.active = 1 

當我使用EXPLAIN時,第一個查詢的索引匹配所有內容。當我運行第二個查詢時,它缺少一個用於我的OR連接的連接。

爲什麼兩個加入比OR更快?結果數據是相同的。

+0

如果你提供的這兩個EXPLAIN結果,我們可以給你更具體的答案。 –

回答

2

首先,這兩個查詢不等價。如果每個表中有一個匹配,那麼第一個將返回一行,第二個將返回兩行。

但是,您的問題的答案是優化問題。 MySQL在or條件下進行優化效果不佳。正如你所注意到的,它忽略了不同指標可以用來滿足每個條件的事實。說實話,這是大多數數據庫引擎的問題。如果你想更好的性能or的效果,然後union all往往效果更好:

SELECT tea.*, loc.* 
FROM teachers AS tea 
    LEFT JOIN availability AS ava 
      ON(tea.teacher_id = ava.teacher_id AND ava.end_date > 1398706428) 
    LEFT JOIN locations AS loc 
      ON(tea.location_id = loc.location_id) 
WHERE tea.active = 1 
union all 
SELECT tea.*, loc.* 
FROM teachers AS tea 
    LEFT JOIN availability AS ava 
      ON(tea.teacher_id = ava.teacher_id AND ava.end_date > 1398706428) 
    LEFT JOIN locations AS loc 
      ON(ava.location_id = loc.location_id) 
WHERE tea.active = 1; 
相關問題