2017-10-12 26 views
1

我有一個包含發佈和發佈標題表的音樂數據庫。這個「releases_view」獲取曲目的標題/ title_id和替代標題/替代title_id。這是視圖的代碼:查詢速度在WHERE子句中的兩個「=」比較中下降

SELECT 
    t1.`title` AS title, 
    t1.`id` AS title_id, 
    t2.`title` AS title_alt, 
    t2.`id` AS title_alt_id 

FROM 
    releases 

LEFT JOIN titles t1 ON t1.`id`=`releases`.`title_id` 
LEFT JOIN titles t2 ON t2.`id`=`releases`.`title_alt_id` 

連接表中的title_idtitle_alt_id字段都int(11)titletitle_alt是VARCHAR處理。

問題

這個查詢只需要不到1毫秒:

SELECT * FROM `releases_view` WHERE title_id=12345 

這個查詢將小於1毫秒,太:

SELECT * FROM `releases_view` WHERE title_id=12345 OR title_alt_id!=54321 

但是:這個查詢將花費0.2秒。 慢200倍!

SELECT * FROM `releases_view` WHERE title_id=20956 OR title_alt_id=38849 

一旦我有使用「=」 WHERE子句中,事情就變得慢(儘管所有查詢只有一對夫婦的結果)兩個比較。

你能幫我理解發生了什麼嗎?

編輯

'EXPLAIN'顯示了使用Where爲title_alt_id,但我不明白爲什麼。我怎樣才能避免這種情況?編輯** 這裏是解釋轉儲。

id select_type  table  partitions type possible_keys key  key_len ref       rows Extra 
1 SIMPLE   releases NULL  ALL  NULL   NULL NULL NULL      76802 Using temporary; Using filesort 
1 SIMPLE   t1   NULL  eq_ref PRIMARY   PRIMARY 4  db.releases.title_id  1  
1 SIMPLE   t2   NULL  eq_ref PRIMARY   PRIMARY 4  db.releases.title_alt_id 1  Using where 
+1

由於兩次比較,速度並沒有降低,它由於OR或JOIN而降低。 – axiac

+0

@axiac,查詢OP指向沒有'JOIN' – Rahul

+0

@axiac:但是示例二也使用了JOIN,它具有OR。您的聲明似乎不是有效的。 –

回答

0

的「很慢」,是因爲優化器不OR很好地工作。

計劃A(優化器):掃描整個表格,評估整個OR

B計劃:「索引合併聯盟」可用於title_id = 20956 OR title_alt_id = 38849如果title_idtitle_alt_id有單獨的索引:使用每個索引來獲得兩個列表PRIMARY KEYs和「合併」的名單,然後將手伸入表得到*。多個步驟,不便宜。所以B計劃很少使用。

title_id = 12345 OR title_alt_id != 54321是一個謎,因爲它應該返回大部分表。請提供EXPLAIN SELECT...

LEFT JOIN(而不是JOIN)需要假定該行可能在'右'表中缺失。