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 OR BA 之间仍然有一个逻辑或条件。

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

History -> team_hash, match_id

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

4

2 回答 2

0

假设 上有一个复合索引{team_a_id, team_b_id},DBMS 可以只使用两个索引查找(一个用于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_id并且team_b_id无论如何要解决散列冲突。更大的数据实际上意味着更小的缓存。
  • 它实际上可能会增加索引的数量 - 引用完整性的有效实施可能需要索引team_a_idteam_b_id即使您不需要它们用于实际的 SQL 查询。除了对缓存施加更大的压力之外,还必须维护每个额外的索引,这可能会损害 INSERT/UPDATE/DELETE 性能。这种情况在 InooDB 中尤为严重,您无法关闭集群,因此二级索引往往比基于堆的表更昂贵(请参阅本文中的“集群的缺点”
于 2012-07-29T20:18:08.643 回答
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) 这样的索引。

于 2012-07-29T21:28:49.287 回答