2012-07-29 24 views
0

我有這樣如下表:數據庫中的兩個列邏輯或索引,或創建單獨的「索引」表

Matches -> match_id, team_a_id , team_b_id, score 

該表將兩支隊伍(A隊和B隊)之間的記錄匹配。然而,有時候A隊會擔任主持人,有時B隊會擔任主持人。因此,當我試圖找到a隊和b隊的歷史比賽時。我目前正在做的是

select * from matches where (team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1); 

有沒有更好的方法來處理這種情況?至於上面的查詢,我是否包含組合team_a_id和team_b_id的索引?但即便如此,我仍然有AB或BA之間的邏輯OR條件。

或者, 我還有一個想法,那就是有另一個表讓說,歷史

History -> team_hash, match_id 

我手動建立team_hash其中hash(a,b) == hash(b,a)。但是這導致插入稍慢,但讀取速度更快。或者它真的更快讀?

回答

0

假設有上{team_a_id, team_b_id}一個綜合指數,數據庫管理系統可以僅使用兩個索引搜索(一個爲team_a_id = 1 and team_b_id = 2,另一個爲team_a_id = 2 and team_b_id = 1),這是非常快的執行SQL語句。我不指望你應該找到缺乏的表現。


但是,有一種方法可以消除這些索引查找之一。添加約束...

CHECK(team_a_id < team_b_id) 

...並且在必要時將「方向」(即,哪個組是主機)編碼在單獨的字段中。這樣,你知道team_a_id = 2 and team_b_id = 1永遠不會是真的,所以你只需要搜索team_a_id = 1 and team_b_id = 2


「對稱」散列是一個不錯的主意,但是:

  • 散列的正確性不能聲明強制執行 - 你需要通過觸發器或在應用層面做到這一點。
  • 這是一個冗餘數據。無論如何你需要保留team_a_idteam_b_id來解決哈希衝突。更大的數據有效意味着更小的緩存。
  • 它實際上可能會增加索引數量 - 即使您不需要它們用於實際的SQL查詢,但有效實施參照完整性可能需要索引team_a_idteam_b_id。除了對高速緩存施加更大壓力外,還必須維護每個附加索引,這可能會影響INSERT/UPDATE/DELETE性能。在InooDB中,情況尤其嚴重,您無法關閉羣集,所以二級索引往往比基於堆的表更貴(請參閱this article中的「羣集的缺點」)。
+0

謝謝你的解釋 – Fajarmf 2012-07-30 01:10:13

+0

uhm btw,可以有跟進問題嗎?假設我們有這些安排,這樣team_a_id Fajarmf 2012-07-30 23:42:21

+0

@Fajarmf但是,如果表中有兩行,會降低緩存的有效性,並且DBMS難以強制執行兩者的存在行。兩種索引的搜索方式仍然應該足夠快,但是如果您已經**測量**效果,可以根據實際的數據量消除其中的一項,並得出結論認爲,此查詢和其他查詢的性能平衡更有利,請放手。我只是不會默認這樣做 - 當面對數據量較小的設計與數據量較大的設計時,默認情況下選擇較小的數據,並且只有在徹底測量後才重新考慮。 – 2012-07-31 09:01:48

0

您也可以讓你的WHERE子句這樣的事情

((team_a_id = 1 and team_b_id = 2) or (team_a_id = 2 and team_b_id = 1)) 
AND team_a_id IN (1,2) AND team_b_id IN (1,2) 

這種方式將有可能使用像(team_a_id,team_b_id)的索引。

+0

爲什麼在最後對這些where子句進行編碼使我只能使用team_a,team_b索引? – Fajarmf 2012-07-30 01:21:04

+0

它可以讓你使用'(team_a_id)','(team_b_id)','(team_a_id,team_b_id)'或'(team_b_id,team_a_id)'索引之一。兩列的人會更好。 – Vatev 2012-07-30 01:27:28

相關問題