2010-07-14 68 views
2

我已经为MySQL中的电影构建了评分系统,但是担心的是,当我的查询总结所有评分并将其分开时,它可能必须总计数百万和数百万条记录。评分系统查询

我想到的一个解决方案是基本上缓存memcached中的评级,并且只对那些用处不大的项目进行评级操作。然而即使如此,对于那些没有被评价很多的电影,如果有人去检查评级,如果需要计算很多行,查询可能需要很长时间。

我想到的另一个解决方案是建立一个不断更新表的临时表,但是如果电影被评为很多并且有人试图访问它,那么我相信INNODB会进行行锁定,所以这个导致僵局或长期的事情?

回答

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 ; 
+0

这是优秀的,我需要的!谢谢 – 2010-07-17 02:42:11