我有这个下表:

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之间的逻辑或条件。

或者, 我有另一个想法,那就是有另一个表让说历史

History -> team_hash, match_id

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

有帮助吗?

解决方案

假设有一个综合指数 {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 无论如何解决哈希冲突。更大的数据实际上意味着更小的缓存。
  • 它实际上可能会增加索引的数量-引用完整性的有效执行可能需要索引 team_a_idteam_b_id 即使您不需要它们用于实际的SQL查询。除了给缓存带来更大的压力之外,还必须维护每个额外的索引,这可能会损害插入/更新/删除性能。在InooDB中,情况尤其严重,因为您无法关闭群集,因此二级索引往往比基于堆的表更昂贵(请参阅"群集的缺点"in 本文).

其他提示

您还可以使您的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)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top