1

我很好奇什么是最好的建模方法以优化性能......不关心实时数据完整性

我将继续使用 stackoverflow 示例

Question
  id
  title
Votes
  id
  user
  question

一个问题有很多票

然而,对于许多查询,我们只关心投票的总数(例如显示在问题旁边)。

良好的关系数据库理论会将两个实体(Q 和 V)创建为单独的关系,需要连接,然后是 sum 或 count 聚合调用。

另一种可能性是打破常规形式,偶尔将投票的总价值具体化为问题中的一个属性(例如 Question.votes)。读取性能会提高,但是,取决于您愿意让您的“投票”数据变得多么陈旧,它需要对该问题记录的更多权限......反过来又会阻碍性能。

可以使用涉及缓存等的其他技术。但我只是想知道,性能方面最好的解决方案是什么?假设该网站的流量更高,并且获得的选票数量比问题多得多。

也对非关系模型开放。

4

3 回答 3

1

在这种情况下,连接不太可能太慢,特别是如果您在 Votes 表中有 (question) 索引。

如果实在是太慢了,你可以在 Question 表中缓存投票数:

 id - title - votecount

每当您记录投票时,您都可以更新投票计数。例如,来自存储过程或直接来自您的应用程序代码。

这些更新很棘手,但由于您并不担心一致性,我想如果投票有时不完全正确也没关系。要修复任何错误,您可以定期重新生成所有缓存计数,例如:

 UPDATE q
 SET votecount = count(v.question)
 FROM questions q
 LEFT JOIN votes v on v.question = q.id

如果未找到问题,则聚合 count(v.question) 返回 0,而 count(*) 则返回 1。

如果锁定是一个问题,请考虑使用“with (nolock)”或“set transaction isolation level read uncommited”来绕过锁定(同样,基于数据完整性是低优先级。)

作为 nolock 的替代方案,请考虑“已提交的读取快照”,它适用于具有大量读取和较少写入活动的数据库。您可以通过以下方式打开它:

ALTER DATABASE YourDb SET READ_COMMITTED_SNAPSHOT ON;

它适用于 SQL Server 2005 及更高版本。这就是 Oracle 默认的工作方式,也是 stackoverflow 本身使用的方式。甚至还有一个关于它的编码恐怖博客条目

于 2009-05-28T21:57:10.690 回答
1

我在社交网站上到处使用 sql 2005 的索引视图来处理这类事情。我们的负载绝对是读/写的高比率,所以它对我们很有效。

于 2009-05-28T22:08:33.070 回答
0

我建议在应用程序的整个生命周期内将投票保留在内存中。为什么要为简单的计数而点击数据库,在某些时候您将加载该项目一次并根据请求询问初始金额是多少。它还与您如何实现存储库有很大关系,如果您的问题对象延迟加载投票但急切加载投票计数,那么您可以加快流程,同时不会将其保存在内存中。仍然将投票保留在 db 中,只需在您的应用程序中保留计数

于 2009-05-28T22:18:47.357 回答