存储总数还是即时计算?

时间:2014-09-20 02:20:01

标签: sql-server database-design sql-server-2012

我的数据库中有很多表格,用于保存用户可以喜欢,不喜欢,共享,喜欢等项目的信息(照片,文章,视频)。

每次用户对某个项目执行操作时,都会将其记录在如下的简单表格中:

ItemID | UserID  | Liked | Shared | Favourited
1        1         NULL    1        NULL
2        25        1       1        1
3        18        0       NULL     NULL

当我编写查询以从表格中返回项目列表(例如照片)时,我还想返回每个项目所拥有的喜欢,股票等的总数。目前我正在使用嵌套的SELECT语句动态计算它。如果我的项目表的大小增加了数十万,并且我经常需要关于喜欢,股票等的统计数据,那么继续计算动态数据是否安全,或者它们是否应该存储在数据库中的某个位置?

4 个答案:

答案 0 :(得分:4)

我建议不要存储总计,因为这似乎是一个事务性数据库,并且您将频繁插入行,因此如果您存储总计,则每次插入行时,都需要更新总计。

因此实际上,表中的每个插入后面都会跟一个更新语句,以便更新总数。对于事务数据库来说,这听起来很糟糕。

对于数据仓库来说,存储总计是一个很好的选择,数据几乎不会发生变化。

我的建议是创建视图,它会动态计算总数。添加适当的索引以使这些查询有效。当您的数据变得太大以至于表上的索引都做得不够时,请考虑索引视图。

答案 1 :(得分:2)

存储总数是邪恶的,因为:

  • 它是一种缓存形式,它本身就是邪恶的(可能不一致,或者至多是非常重要的)。有关详细信息,请参阅http://shouldiblamecaching.com
  • 可能是错的!除非您涵盖所有数据修改可能性(例如触发器),否则可能存在错误 - 即存储的总数可能不正确。错误的数据比慢速数据差1000倍
  • 更复杂:您已为系统添加了另一个方面。应避免复杂性
  • 不必要或没有用处 - 除非您有文件证明通过查询进行操作是不可行的,并且您已经困扰所有查询优化,否则您不需要这样做。即使你认为你确实需要它,你也许不会。例如,您可以将操作拆分为使用dara仓库以获取稳定数据(例如超过1周),其中存储每天的总计,并使用实时系统处理最近的所有内容,将查询管限制为仅扫描最近一周的数据(应该执行OK)。如果表现仍然是一个问题,缩小" live"窗口到一天。我做到了这一点并且效果很好。

答案 2 :(得分:1)

如果是我,我会偶尔计算一次并将结果存储在另一张表中。如果计数对于像“有多少人喜欢小猫”这样的东西而言不是那么准确,那么这并不是什么大问题。

答案 3 :(得分:1)

另一方面,如果您希望获得一百万个“观看次数”,并且必须COUNT(*)来检索该计数,那么Performance可能会否决“邪恶”。

对于大容量情况,我建议以下之一:

计划A:即时进行计数。 UPDATE ViewCounts SET ct = ct + 1 WHERE page_id = ?请注意,这是故意与“页面”的其余元信息放在单独的表中。这是为了减少两者之间的干扰。 (或者,您也可以将每个“视图”的详细信息保留在另一个表中。)

计划B:有一张表格,其中包含有关每个“视图”的信息,但是每小时(每天)每小时(一天)执行COUNT(*),并将结果放入“摘要表”中。然后从该表中SUM(subtotal)获得总体视图。这样的表格还可以为视图中的“趋势”提供图表信息。

注意:这两个计划都假定事实之后数据不会更改。处理原始“视图”表中的删除内容变得很复杂。