数据库两列逻辑OR索引,或创建单独的'索引'表

时间:2012-07-29 19:39:28

标签: mysql database database-design indexing two-columns

我有以下表格:

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 OR BA之间存在逻辑OR条件。

替代地下, 我有另一个想法,就是让另一张桌子说历史

History -> team_hash, match_id

我手动构建了team_hash hash(a,b) == hash(b,a)。但这会导致插入稍慢但读取速度更快。或者读取真的更快?

2 个答案:

答案 0 :(得分:0)

假设{team_a_id, team_b_id}上有一个复合索引,DBMS只能使用两个索引搜索执行您的SQL语句(一个用于team_a_id = 1 and team_b_id = 2,另一个用于team_a_id = 2 and team_b_id = 1),非常快。我不认为你应该发现缺乏表现。


然而,有一种方法可以消除这些指数寻求之一。添加约束...

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中的“群集的缺点”)。

答案 1 :(得分: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)这样的索引。