更新频繁的计数器列是否应该单独存储在table中?

Should a counter column with frequent update be stored in a separate table?

我有一个 MySQL/MariaDB 数据库,其中存储了 post。每个post都有一些统计指标,比如post当天的浏览次数、总浏览次数、点赞数等。 现在,我计划在每次发生操作时更新 real-time 中的所有计数器列 - post 获得一个视图,喜欢或不喜欢。这意味着 post_stats table 会一直更新,而 posts table 很少更新,大部分时间只会被读取。

table架构如下:
posts(post_id, author_id, 标题, slug, 内容, created_at, updated_at)
post_stats(post_id, total_views, total_views_今天, total_likes, total_dislikes)

两个table用一个post_id外键连接。目前,table 都使用 InnoDB。来自两个 table 的数据将始终一起查询,以便能够显示 post 及其计数器,因此这意味着将一直使用 INNER JOIN。统计信息在阅读后立即更新(每次页面浏览)。

我的问题是:

  1. 为了在 table 增长时获得最佳性能,我是否应该将两个 table 合并为一个,因为 post_status 中的列与 post 直接相关条目,或者我应该将 counter/summary table 与主要 posts table?
  2. 分开
  3. 为了在 table 增长时获得最佳性能,我是否应该将 MyISAM 用于 posts table 因为我可以想象 MyISAM 在读取时效率更高,而 InnoDB 在插入时效率更高?

这个问题是这个数据库的普遍问题,也适用于同一数据库中的其他 table,例如 users 等计数器 他们 posts,他们写的总评论数,他们写的总posts,等等)和 categories该类别中 post 的数量 ,等等)。

编辑 1:每天的观看次数计数器在每天午夜通过 cron 作业重置一次。

编辑 2:postspost_stats 作为两个 table 的原因之一是对缓存的担忧。

  • 对于低流量,KISS -- 将计数器保留在主 post table 中。 (我假设你已经排除了这种可能性。)

  • 对于高流量,将计数器放在单独的 table 中。但是让我们以不同的方式处理“今天的”计数器。 (这就是你要讨论的。)

  • 对于非常高的流量,收集计数以便每个 click/view/like 可以执行少于 1 次更新。 (“汇总表”超出了这个问题的范围。)

学习一下total_views_today。您是否必须在每个午夜都进行一次大的“重置”?那是(或将变得)成本太高,所以让我们尽量避免它。

  • 在table中只有total_views
  • 在午夜将 table 复制到另一个 table。 (SELECT 比重置值所需的 UPDATE 更快,less-invasive。)通过构建新的 table 来完成此复制,然后 RENAME TABLE 移动它到位。
  • 通过减去两个table中的相应值来计算total_views_today

那给你留下了

post_stats(post_id, total_views, total_likes, total_dislikes)

对于“高流量,做就好了

UPDATE post_stats SET ... = ... + 1 WHERE post_id = ...;

在需要的时候(每个计数器)。

但是有一个潜在的问题。如果该行不存在,则不能增加计数器。最好通过在创建 post 的同时创建一个包含零的行来解决这个问题。 (否则,请参阅 IODKU。)

(想多了可能还会回来)