【问题标题】:How should something like SO's vote count be stored in a database?SO的投票数之类的东西应该如何存储在数据库中?
【发布时间】:2020-08-25 19:11:19
【问题描述】:

我假设 StackOverflow 上的投票是用户和帖子之间的关系。计算每个页面加载的投票会很昂贵,所以我假设它缓存在某个地方。是否有存储可以从其他数据库数据计算的值的最佳做法?

  1. 我可以将它存储在 Redis 之类的东西中,但是按投票对问题进行排序会很昂贵。

  2. 我可以将它作为新列存储在帖子表中,但它会使其他工程师感到困惑,因为派生值通常不与实际数据一起存储。

  3. 我可以为派生数据创建一个实体-属性-值表,这样我就可以将它与帖子表连接起来。连接对性能有轻微影响,我不喜欢用非结构化数据填充表的想法,因为它很容易最终被未使用的数据填充。

我使用的是 MySQL 8,还有其他选择吗?

还有一点需要考虑的是,这个数据不需要保持一致,如果总票数稍有偏差也没关系。因此,当创建投票时,不需要立即更新投票总数,可以定期运行作业来更新投票。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    “最佳实践”在很大程度上取决于情境,并且通常基于意见。这是我的看法。

    您的问题似乎是关于如何使数据库驱动的应用程序大规模执行,以及哪些权衡是可以接受的。

    我会尽可能长时间地坚持使用关系规范化数据模型。您说“计算每个页面加载的选票会很昂贵” - 可能不会那么昂贵,因为您将加入外键,除非您谈论的是非常大量的记录和/或请求,应该可以很好地扩展。

    如果可扩展性和性能是挑战,我会构建一个测试平台,优化这些查询,对它们进行负载和性能测试,并在做任何其他事情之前添加硬件容量。

    这是因为没有复制/缓存的规范化数据库和应用程序更容易维护,不太可能出现奇怪的错误,并且更容易在未来扩展。

    如果你达到了不再起作用的地步,我会考虑缓存。这里有一系列选项——你提到了 3。挑战在于,一旦你达到规范化数据库因为性能瓶颈的地步,通常会有很多潜在的查询成为瓶颈——如果你优化“多少票有帖子吗?”查询,您将问题转移到“有多少人查看了此帖子?”查询。

    所以,此时我通常会尝试通过在应用层缓存来限制对数据库的请求。这可以采用 Redis 缓存的形式。按效果降序排列,您可以:

    • 缓存整个页面。这大大减少了数据库点击次数,但对于像 SO 这样的个性化网站则很难做到。
    • 缓存页面片段,例如SO主页有几十个问题;您可以将每个问题缓存为 HTML 的 sn-p,并组装这些 sn-ps 以呈现页面。这允许您通过为不同的用户组合不同的片段来创建个性化页面。
    • 缓存查询结果。这意味着应用服务器需要解释查询结果并转换为 HTML;您将这样做是为了缓存用于组装页面的数据。对于 SO,比如你可以缓存“Leojiang的头像路径是x,并且他们跟随标签{a,b,c}”。

    当然,缓存的问题在于失效以及性能和最新信息之间的权衡。您还可能会遇到许多奇怪的错误,即缓存在负载均衡器之间不同步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 2012-07-19
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 2014-07-14
      相关资源
      最近更新 更多