评级系统查询

发布于 2024-09-09 01:02:48 字数 268 浏览 1 评论 0原文

我在 MySQL 中构建了一个电影评级系统,但问题是,当我的查询汇总所有评级并进行除法时,它可能需要汇总数百万条记录。

我想到的一种解决方案是基本上将评级缓存在 memcached 中,并且只对不经常使用的项目进行评级操作。然而,即使如此,对于评级不高的电影,如果有人去检查评级,如果必须计算大量行,查询可能会花费很长时间。

我想到的另一个解决方案是建立一个不断更新表的临时表,但是如果电影评级很高并且有人试图访问它怎么办,我相信 INNODB 会进行行锁定,所以这会导致死锁或从长远来看?

I've built a rating system for movies in MySQL, however the concern is that when my query sums up all the ratings and divides it, it might have to sum up millions and millions of records.

One solution I thought of was to basically cache the rating in memcached and only do the rating operation for items which are not used a lot. However even then for movies which are not being rated a lot if someone does go check the rating that query might take a long time if it has to calculate a lot of rows.

Another solution i thought of was to build a temporary table which is constantly updating the table, however what if the movie is being rated a lot and someone is trying to access it, INNODB i believe does row locking, so will this cause a deadlock or something in the long run?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

赠意 2024-09-16 01:02:48

由于评级相当静态并且您的数据集很大,因此当用户对电影进行评级时,您可以缓存(非规范化)电影记录中的数据。您需要跟踪投票数和投票总和,以便平均值是准确的。您的电影评级会在您需要时动态计算。这是架构:

create table movie as (
movie_id int not null primary key,
-- your current columns
vote_count int,
vote_sum int
);

然后使用视图来帮助

create view movie_view as
select
  *,
  vote_sum/vote_count as vote_average
from movie;

假设您有一个如下所示的表:

create table user_movie_vote (
user_id int references user,
movie_id int references movie,
vote int
);

您可以使用触发器来使投票总数保持最新:

delimiter ~
create trigger movie_vote_trg after insert on user_movie_vote
for each row
begin
  update movie set
  vote_count = vote_count + 1,
  vote_sum = vote_sum + new.vote
  where movie_id = new.movie_id;
end~
delimiter ;

如果可以更新投票,您将需要:

delimiter ~
create trigger movie_vote_trg after update on user_movie_vote
for each row
begin
  update movie set
  vote_sum = vote_sum + new.vote - old.vote
  where movie_id = new.movie_id;
end~
delimiter ;

如果投票可以删除,你需要:

delimiter ~
create trigger movie_vote_trg after delete on user_movie_vote
for each row
begin
  update movie set
  vote_sum = vote_sum - old.vote,
  vote_count = vote_count - 1
  where movie_id = new.movie_id;
end~
delimiter ;

Since ratings are fairly static and your dataset is large, you could cache (denormalize) the data in the movie record when a user rates a movie. You need to keep track of the number of both votes and the sum of the votes, so the average is accurate. Your movie rating is dynamically calculated when you need it. Here's the schema:

create table movie as (
movie_id int not null primary key,
-- your current columns
vote_count int,
vote_sum int
);

then use a view to help out

create view movie_view as
select
  *,
  vote_sum/vote_count as vote_average
from movie;

assuming you have a table that looks like this:

create table user_movie_vote (
user_id int references user,
movie_id int references movie,
vote int
);

you could use a trigger to keep the vote totals up to date for you:

delimiter ~
create trigger movie_vote_trg after insert on user_movie_vote
for each row
begin
  update movie set
  vote_count = vote_count + 1,
  vote_sum = vote_sum + new.vote
  where movie_id = new.movie_id;
end~
delimiter ;

if votes can be updated, you'll need:

delimiter ~
create trigger movie_vote_trg after update on user_movie_vote
for each row
begin
  update movie set
  vote_sum = vote_sum + new.vote - old.vote
  where movie_id = new.movie_id;
end~
delimiter ;

if votes can be deleted, you'll need:

delimiter ~
create trigger movie_vote_trg after delete on user_movie_vote
for each row
begin
  update movie set
  vote_sum = vote_sum - old.vote,
  vote_count = vote_count - 1
  where movie_id = new.movie_id;
end~
delimiter ;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文