计算帖子的平均评分

时间:2018-08-22 14:03:46

标签: php mysql sql

我有以下实体:

post_id | post_title | post_body
-------------------------------------
1       | First post | Hello, world!

,并希望在帖子上注册评分,就像这样:

rating_id | rating_user_id | rating_post_id | rating_rating
1         | 23             | 1              | 3.5

我主要关心的问题是如何获取帖子的平均评分。我知道我可以这样使用SQL查询来做到这一点:

SELECT AVG(rating_rating) FROM post_ratings WHERE rating_post_id = 2;

但是我每次都要$post->getAverageRating()时都必须调用此查询-这是一个很大的性能问题吗? (请注意,每个帖子可能会有成千上万的评分)

一种替代方法是将平均评分存储在posts表的新列中,并安排cron作业计算平均值?

解决此问题的最佳方法是什么?

3 个答案:

答案 0 :(得分:1)

关于性能比较-取决于

  1. 评分的静态性。如果您希望现有帖子有新的评分,无论如何我都会即时进行计算。
  2. 相对于总体帖子,您需要多少个帖子的评分。如果您有数以百万计的帖子,并且只需要几千条的平均评分,那么也可以分开进行。

答案 1 :(得分:1)

这是效率问题

如果这些额定值和哪些额定值会大量叠加,则最好保存计算出的平均值 我会在posts表中添加2列,average_rating,total_ratings

ALTER TABLE posts ADD COLUMN average_rating DECIMAL (9,2);
ALTER TABLE posts ADD COLUMN total_ratings UNSIGNED (9) DEFAULT 0;

并在添加新评分时填充它们,因此您无需进行Cron工作 请注意查询的顺序以计算平均值

MySQL + PHP代码应类似于:

    $query = "UPDATE posts SET total_ratings  = total_ratings + " . $rating_rating . " WHERE post_id = " . $post_id;
    $db->query($query);
    $query = "UPDATE posts SET average_rating = average_rating * (total_ratings -1 / total_ratings) + " . $rating_rating ." / total_ratings WHERE post_id = " . $post_id;
$db->query($query);

这样,您可以立即更新posts表,而无需执行任何cron作业

答案 2 :(得分:1)

数据库调用非常昂贵,尤其是当您每次必须求平均值时。

与当前解决方案相比,您具有以下最佳选择。

  1. 具有一列,用于计算和存储帖子的平均评分,如@Guy L所述。

  2. 使用TTL(生存时间)实现缓存

示例:

public function getAverageRating() {
     $post_id = 'post' . $this->id;
     if(Cache::has($post_id))
         return Cache::get($post_id);
     $rating = //fetch rating from DB
     Cache::set($post_id, $rating, 120); //ratings will be in the cahce for 120secs
     return $rating
}

希望有帮助。