Рейтинг системы запросов - PullRequest
2 голосов
/ 14 июля 2010

Я построил систему оценки для фильмов в MySQL, однако проблема заключается в том, что, когда мой запрос суммирует все оценки и делит его, может потребоваться суммирование миллионов и миллионов записей.

Одним из решений, о котором я подумал, было в основном кэшировать оценку в memcached и выполнять операцию оценки только для элементов, которые не используются часто.Однако даже в этом случае для фильмов, которые не получают высокой оценки, если кто-то идет, проверьте рейтинг, этот запрос может занять много времени, если он должен вычислить много строк.

Другое решение, о котором я подумал, было создатьвременная таблица, которая постоянно обновляет таблицу, но что, если фильм оценивается много, и кто-то пытается получить к нему доступ, я считаю, что INNODB блокирует строки, так что это вызовет тупик или что-то в долгосрочной перспективе?

1 Ответ

4 голосов
/ 15 июля 2010

Поскольку оценки довольно статичны, а набор данных большой, вы можете кэшировать (денормализовать) данные в записи фильма, когда пользователь оценивает фильм. Вам необходимо отслеживать количество обоих голосов и сумму голосов, поэтому среднее значение является точным. Рейтинг вашего фильма рассчитывается динамически, когда вам это нужно. Вот схема:

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 ;
...