2

私はMySQLで映画の評価システムを構築しましたが、私のクエリがすべての評価を合計してそれを分割すると、何百万ものレコードを合計しなければならない可能性があるという懸念があります。

私が考えた解決策の1つは、基本的にmemcachedに評価をキャッシュし、あまり使用されていないアイテムに対してのみ評価操作を実行することでした。ただし、それでも、誰かが行った場合にあまり評価されていない映画の場合、多くの行を計算する必要がある場合は、クエリに長い時間がかかる可能性があります。

私が考えたもう1つの解決策は、テーブルを常に更新する一時テーブルを作成することでしたが、映画の評価が高く、誰かがそれにアクセスしようとすると、INNODBは行ロックを行うと信じているので、デッドロックが発生するか、長期的には何か?

4

1 に答える 1

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 ;
于 2010-07-15T03:43:45.327 に答える