我已经为MySQL中的电影建立了一个评级系统,但关注的是当我的查询总结所有评级并对其进行划分时,它可能需要总结数百万条记录。
我想到的一个解决方案是基本上在memcached中缓存评级,并且只对未经常使用的项目进行评级操作。然而,即便如此,对于没有被评级很多的电影,如果有人确实去检查评级,如果必须计算很多行,查询可能需要很长时间。
我想到的另一个解决方案是构建一个不断更新表的临时表,但是如果电影被评级很多并且有人试图访问它,我相信INNODB会进行行锁定,所以这会导致从长远来看是僵局还是什么?
答案 0 :(得分:4)
由于评级相当静态且数据集很大,因此您可以在用户评价电影时缓存(非规范化)电影记录中的数据。您需要跟踪两个投票的数量和投票的总和,因此平均值是准确的。您的电影评级是在您需要时动态计算的。这是架构:
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 ;