2011-02-09 19 views
2

我有36萬記錄的表和這裏的兩個索引字段進行查詢:使用JOIN'ed映射表比同一個表中的多個字段更好嗎?

SELECT COUNT(*) 
FROM emails 
WHERE 
department_id IN(1,2,3,4) 
AND category_id IN (5,6,7,8) 

(Time: 0.9624802) 

      id: 1 
    select_type: SIMPLE 
     table: emails 
     type: range 
possible_keys: emails_department_id_idx,emails_category_id_idx 
      key: emails_category_id_idx 
     key_len: 5 
      ref: NULL 
     rows: 54018 
     Extra: Using where 

所以只有一個索引被使用在那裏。 (當使用更簡單的比較或範圍標準時,我可以獲得索引合併的工作,但是我需要根據ID列表進行這種檢查)。

在這裏,我創建了兩個新表映射這種關係,並使用JOIN的我複製了相同的結果:

SELECT COUNT(*) 
FROM emails 
LEFT JOIN email_to_department ON (email_to_department.email_id = emails.id AND email_to_department.department_id IN (1,2,3,4)) 
LEFT JOIN email_to_category ON (email_to_category.email_id = emails.id AND email_to_category.category_id IN (5,6,7,8)) 
WHERE 
email_to_department.department_id IS NOT NULL 
AND email_to_category.category_id IS NOT NULL 

(Time: 0.5217777) 

*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: email_to_category 
     type: range 
possible_keys: PRIMARY,category_id 
      key: category_id 
     key_len: 4 
     ref: NULL 
    rows: 61282 
    Extra: Using where; Using index 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: email_to_department 
     type: ref 
possible_keys: PRIMARY,department_id 
      key: PRIMARY 
     key_len: 4 
      ref: testdb.email_to_category.email_id 
     rows: 1 
     Extra: Using where; Using index 
*************************** 3. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: emails 
     type: eq_ref 
possible_keys: PRIMARY 
      key: PRIMARY 
     key_len: 4 
      ref: testdb.email_to_category.email_id 
     rows: 1 
     Extra: Using index 
3 rows in set (0.38 sec) 

所以每個查詢現在使用的指標,並修剪幾乎一半的時間了。這是不好的設計?我應該以同樣的方式寫下其餘的這些關係嗎?

如果我以相同的方式添加更多條件,JOIN'd版本的查詢似乎變得更快,另一個保持大致相同。

上做只是一個單一的索引字段一個簡​​單的查詢是非常非常快,當然:

SELECT COUNT(*) 
FROM emails 
WHERE department_id IN(1,2,3,4) 

是否有另一種策略,我可以使用,使這些類型的查詢速度還是?還有其他一些屬性需要進行過濾以及以不同的組合方式進行過濾,因此創建多列索引並不會真正起到幫助作用。

+0

在您的第一個查詢中,您可能希望考慮在department_id和category_id上添加一個關鍵字INDEX(department_id,category_id)。這將有助於使用索引的第一個查詢過濾器結果。 – JamesHalsall

回答

0

我也同意Jaitsu關於在兩個字段上創建複合鍵。通常,您應該始終將組合索引中具有較高基數的列置於首位。這樣你可以有更多的選擇性指數。

1

這實際上是一個關於數據庫規範化的問題。您可以在許多地方查找有關該主題的信息。

基本回答由於這方面有大量的文獻,而且有很多不同之處,所以我只想指出,它歸結爲折衷;速度與存儲要求,或易用性與數據複製。你可能想了解歸一化是爲了理解你爲什麼要這麼做或不想做什麼。

進一步閱讀這是一個很深的話題,您可能想了解更多 - 有數百本書和數千篇關於這些問題的學術論文。例如,看看這個前面關於設計數據庫的SO問題: Database design: one huge table or separate tables?,或者這個:First-time database design: am I overengineering?Database Normalization Basics 在About.com上。

相關問題