我有以下表格:
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)
。但这会导致插入稍慢但读取速度更快。或者读取真的更快?
答案 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_id
和team_b_id
来解决哈希冲突。较大的数据实际上意味着较小的缓存。team_a_id
和team_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)这样的索引。