【问题标题】:database two column logical OR index, or create separate 'index' table数据库两列逻辑或索引,或创建单独的“索引”表
【发布时间】:2012-07-27 13:56:02
【问题描述】:

我有这个下表:

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)。但这会导致插入速度稍慢但读取速度更快。还是读起来真的更快?

【问题讨论】:

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


    【解决方案1】:

    假设{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_idteam_b_id 以解决散列冲突。更大的数据实际上意味着更小的缓存。
    • 它实际上可能会增加索引的数量——有效地执行引用完整性可能需要team_a_idteam_b_id 上的索引,即使您在实际的SQL 查询中不需要它们。除了对缓存施加更大的压力之外,还必须维护每个额外的索引,这可能会损害 INSERT/UPDATE/DELETE 性能。这种情况在 InooDB 中尤为严重,您无法关闭集群,因此二级索引往往比基于堆的表更昂贵(请参阅 this article 中的“集群的缺点”)。

    【讨论】:

    • 感谢您的解释
    • 嗯顺便说一句,可以有后续问题吗?假设我们有这些安排,因此 team_a_id select * from matches where team_a_id = 1 or team_b_id = 1 然后我最终遇到了与 AB 或 BA 类似的情况。所以我在想只是复制比赛的每个条目不是更好吗?所以我有A,B, host 和另一条记录B,A,away。那么对于我的新案例,我可以快速做select * from matches where team_a_id = 1
    • @Fajamf 但是你在表中有 2x 行,降低了缓存的有效性,并且 DBMS 难以强制两行的存在。两个索引搜索应该仍然很快,但是如果您测量消除其中一个对实际数据量的影响,并得出结论认为此查询和其他查询的性能平衡更有利,请选择它。我只是默认不会这样做 - 当面对具有较小数据的设计与具有较大数据的设计时,默认选择较小的数据,并且只有在彻底测量后重新考虑。
    【解决方案2】:

    你也可以让你的 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) 这样的索引。

    【讨论】:

    • 为什么最后编码这些 where 子句使我只能使用 team_a,team_b 索引?
    • 它将使您能够使用(team_a_id)(team_b_id)(team_a_id,team_b_id)(team_b_id,team_a_id) 索引之一。有两列的会更好。
    猜你喜欢
    • 1970-01-01
    • 2013-01-04
    • 2014-08-25
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多