2011-03-28 59 views
5

假设我有一组产品,每个产品都有一组评论。每个评论都有一个分数。我会更频繁地需要得分的平均值,那么我将需要实际的评论。是否有任何最佳实践/预先计算平均值的干净方式并将其与休眠存储在一起。使用休眠计算和存储预先计算的平均值

我目前正在考虑在产品表中添加评论数量和评论总和列,并使用添加评论方法来更新计数和总和。

我会很高兴听到一个更干净的方式做到这一点。

回答

2

我会建议不要在父表上保留一个总和列。如果两个相互竞争的请求尝试更新总和列,则会失败,或者冒着破旧的读取风险(除非系统没有高流量...)。

您所需要的查询是非常简单,任何像样的数据库应给予一段时间(懒惰伪SQL/HQL)性能好:

1)一个特别的平均评价得分为产品:

select sum(score)/count from reviews where product_id = ? 
产品

2)名单和他们的平均的评分

select product_name, sum(r.score)/count(r.score) 
from products p 
join reviews r 
group by product_name 

对于第一个查询,请确保您有某种指数上的评论表PRODUCT_ID。

使用hibernate,您可以通过HQL或Criteria objects使用投影查询。如果这还不够快,那么我会考虑second level caching and query caching

打开show_sql和TestTestTest以确保hibernate只打一次数据库,并且在添加/更新新项目时缓存失效。

+0

我打算用这个或一个触发器捆绑一个触发器,在添加或更新评论后获取带有CacheMode.REFRESH的产品。 – user472749 2011-03-30 02:32:26

+0

实际上有更好的方式从二级缓存中驱逐。 http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-sessioncache – user472749 2011-04-04 20:10:45

0

我认为有一个更好的方法,一个后台进程不时运行,并根据评论表对产品表中的计数和总评级进行更新。

另一个想法是使用一个触发器,每当检查/评估表中有一个更新时,就会考虑它(使用时间戳)并更新产品表。

+0

我的想法是基于让你的应用程序做它的意思。这与汇总或分析类似,让它分开处理,例如。有些时候你可能需要“上个月的评级增长”,所以我们可以倾向于将这种功能远离我们的定期更新代码。 – Ankur 2011-03-28 02:48:43

+0

如果使用了触发器,那么旧数据不会保留在二级缓存中吗? – user472749 2011-03-28 03:28:26

+0

@ user472749我不明白你在问什么,如果我们使用触发器它会更新产品表中的计数以计数+ 1并将评级评级为+ thisRating,以便下一次从产品表中提取数据并计算平均值这将是正确的。 – Ankur 2011-03-28 03:41:05