PHPとMySQLで人気投票のシステムを作りたいのですが、


良いアイデアというか設計がまとまらず悩んでいます。

現在の状況は、商品DBがありまして1レコードずつに商品データが格納されている状態です。

そこに、人気投票のフィールドを追加するのが一番簡単なのですが以下の問題があります。

1.ただ単に加算するので、日別、月別、年別などにわけることが出来ない。

2.1商品に対して1日1回の投票にしたいのですが、この場合javascriptでしか制御できないため無効にしている人には効果が無い。

3.商品レコードを呼び出して、人気フィールドの値に加算するため最低2クエリ必要。なるべく1回にしたい。

解決策として以下の処理を考えています。

1.投票DBを制作し1クリック毎にレコードを追加。
この場合、Cronなどを使って一定の期間で何らかの処理をしないと量が多くなりそう…
どのくらいの、期間でどんな処理をすればよいのでしょうか?

2.商品毎にカウントDBを作成する。
テーブルが多くなりすぎて面倒そうです…

日別、月別、年別の集計のほかに前日比みたいな感じも機能として欲しいのですが、

どう、うまくまとめれば良いでしょうか?

回答の条件
  • 1人10回まで
  • 登録:
  • 終了:2010/11/22 12:47:45
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:windofjuly No.1

回答回数2625ベストアンサー獲得回数1149

ポイント40pt

【0】主催者の読みや要求はどのくらいなのかによります

この手の設計には「単位時間あたりに投稿される件数」の見積が重要となりますので、

まずは、毎時どれくらいの投稿が発生するかを見積もってください(データベースの設計・構築に大きく関わります)

さらには、毎分どれくらいの投稿が発生するかも見積もってください(ロジックの設計・構築に大きく関わります)

 

投稿数は普段のページビューなどを参考にしますが、まったく新規の案件であるならば、

主催者がどのくらいの投稿数を希望しているのかを基準にして余裕を持たせるという考え方になったりします

 

 

【1】データベース側は専用のテーブルを用意するのが良いですね

・1.投票DBを制作し1クリック毎にレコードを追加が良いでしょう

 毎時1万レコードの追加があったとしても容量なんかはしれてます

 

【2】集計タイミング

・投稿用とは別のテーブルを用意して、24時間に一度、集計結果を追記していけばよいでしょう

・途中経過が欲しければ1-2時間に1回などでも良いでしょう

 ただし、常に最新の途中経過を表示するような仕様になってしまうと、

 サーバ負荷が大きすぎると思うので、定時発表にしておくのが良いでしょう

・いずれの集計作業もサーバ自身が毎朝4時頃に行う維持管理作業を避けるようにしましょう

 (サーバの設置されている国によって時差があるので注意)

 

【3】年別の集計

・長期運用を行うのであれば投稿用はパーティショニングを用いて分離しておくと良いでしょう

 http://dev.mysql.com/doc/refman/5.1/ja/partitioning-management.h...

 古いデータは集計結果だけを残すようにして、

 月単位くらいでバックアップや消去していく流れにすれば管理は楽です

 

【備考】サーバ負荷は極力減らしましょう

javascriptが使えない状況では投稿できないようにしてしまうくらいのことが必要になる場合もあります

それは無理だとしても、クッキーを使って多重投稿されないような仕組みくらいは構築しましょう

 

ざっくりとした質問なので、以上ざっくりとお答えさせていただきました

(不明点があれば、コメント欄でよろしくです)

id:black_kenchan

とても参考になりました。

本当に有難う御座います。

2010/11/19 22:35:37

その他の回答3件)

id:windofjuly No.1

回答回数2625ベストアンサー獲得回数1149ここでベストアンサー

ポイント40pt

【0】主催者の読みや要求はどのくらいなのかによります

この手の設計には「単位時間あたりに投稿される件数」の見積が重要となりますので、

まずは、毎時どれくらいの投稿が発生するかを見積もってください(データベースの設計・構築に大きく関わります)

さらには、毎分どれくらいの投稿が発生するかも見積もってください(ロジックの設計・構築に大きく関わります)

 

投稿数は普段のページビューなどを参考にしますが、まったく新規の案件であるならば、

主催者がどのくらいの投稿数を希望しているのかを基準にして余裕を持たせるという考え方になったりします

 

 

【1】データベース側は専用のテーブルを用意するのが良いですね

・1.投票DBを制作し1クリック毎にレコードを追加が良いでしょう

 毎時1万レコードの追加があったとしても容量なんかはしれてます

 

【2】集計タイミング

・投稿用とは別のテーブルを用意して、24時間に一度、集計結果を追記していけばよいでしょう

・途中経過が欲しければ1-2時間に1回などでも良いでしょう

 ただし、常に最新の途中経過を表示するような仕様になってしまうと、

 サーバ負荷が大きすぎると思うので、定時発表にしておくのが良いでしょう

・いずれの集計作業もサーバ自身が毎朝4時頃に行う維持管理作業を避けるようにしましょう

 (サーバの設置されている国によって時差があるので注意)

 

【3】年別の集計

・長期運用を行うのであれば投稿用はパーティショニングを用いて分離しておくと良いでしょう

 http://dev.mysql.com/doc/refman/5.1/ja/partitioning-management.h...

 古いデータは集計結果だけを残すようにして、

 月単位くらいでバックアップや消去していく流れにすれば管理は楽です

 

【備考】サーバ負荷は極力減らしましょう

javascriptが使えない状況では投稿できないようにしてしまうくらいのことが必要になる場合もあります

それは無理だとしても、クッキーを使って多重投稿されないような仕組みくらいは構築しましょう

 

ざっくりとした質問なので、以上ざっくりとお答えさせていただきました

(不明点があれば、コメント欄でよろしくです)

id:black_kenchan

とても参考になりました。

本当に有難う御座います。

2010/11/19 22:35:37
id:b-wind No.2

回答回数3344ベストアンサー獲得回数440

ポイント20pt

1.投票DBを制作し1クリック毎にレコードを追加。

この場合、Cronなどを使って一定の期間で何らかの処理をしないと量が多くなりそう…

どのくらいの、期間でどんな処理をすればよいのでしょうか?

集計処理なんて管理者がわで見れればよいもんじゃないの?

管理画面で見るだけならリアルタイムに集計して5分ぐらいかかっても良さそうなもんだが。

(さすがにそれ以上だとタイムアウトになる可能性があるね)


エンドユーザーにも見せたいなら集計結果格納用のテーブルでも作って、

定期的に集計結果を入れ替えるようにするだけじゃないかな。

どのくらいの、期間でどんな処理をすればよいのでしょうか?

逆に聞くけど、どのくらいの期間でどんなデータの見せたいの?



2.商品毎にカウントDBを作成する。

テーブルが多くなりすぎて面倒そうです…

テーブルが都度増えるという設計は無しだ。

詳しい説明は省くけど、あとで泣きを見るのは確実。

id:black_kenchan

有難う御座います。

2010/11/22 12:46:20
id:tama213 No.3

回答回数486ベストアンサー獲得回数30

ポイント40pt

>この場合javascriptでしか制御できないため無効にしている人には効果が無い。

クッキーだけ使えば、制御できるはずです。

でもクッキー無効にしてる人には効果がないですね。

違うんです、クッキーを無効にしてたり、Javascriptを無効にしてたら投票できないように

するのです。そもそも、この2つを無効にしてる人なんて、普通の人ではほとんどいません。

無効にしてるのは、変な人たちだけです。

携帯電話からの投票とか考慮してるのなら話は別ですが・・。

----------------------------------

>1.投票DBを制作し1クリック毎にレコードを追加。

>この場合、Cronなどを使って一定の期間で何らかの処理をしないと量が多くなりそう…

>どのくらいの、期間でどんな処理をすればよいのでしょうか?

投票データが1日でどの程度になるとかそういう推測がなければなんともできないけど。

10万件とかその程度では多いとは思えないけど、そのあたりの感覚は、

用意できるサーバーリソースとかによる。

このあたりを考慮して一月単位ですむならその方向で。

>2.商品毎にカウントDBを作成する。

>テーブルが多くなりすぎて面倒そうです…

カウントDBテーブルのフィールドに「商品コード」をいれれば

ひとつですみます。

>日別、月別、年別の集計のほかに前日比みたいな感じも機能として欲しいのですが

その都度、SQLで集計すれば?

投票データの件数にもよるけど、そんなに多くないのなら。


経験ないんだったら、頭の中だけで設計できないよ。

実際にデータを作って、応答時間を計ったりいろいろしないと。

それか、プロトタイピング技法をつかって、とりあえず作って

問題あるところを改善していく。

集計データもSQLで毎回集計して表示してもいいわけですし、

それで速度的に問題あるのなら、1日ごとや1月ごととかに

プログラムを走らせて集計すればよいのです。

id:black_kenchan

とても参考になりました。

本当に有難う御座います。

2010/11/22 12:46:04
id:yugmix No.4

回答回数27ベストアンサー獲得回数3

ポイント40pt

商品DB(TABLE)

商品ID 投票数

投票DB(TABLE)

id(dummy primarykey) 投票者識別ID(Cookie等から生成) 投票日時 商品ID (sub key)

というようなDB設計をします。

実際の投票は、即時 投票DB に入れるのではなく、別ファイルへ書き出しておく形でも良いと思います(数分単位でバッチで 投票DB に追加等)

1日に1回以上の投稿は 投票DB から投票者識別ID/投票日時 をベースに弾くようにします。

もしくは前述の別ファイルへの書き出しを使うのなら、処理上は acceptしたようにみせかけて DB には追記しないようにします。

投票DB は 一定集計期間(数時間~1日?) 毎に 商品ID で count / group by をかけて結果を 商品DB へ反映させます。

その後、集計後の投票DBは(情報として必要がないのなら) alter で TABLE の名前を変えた後、新たに 投票DB を CREATE します。 古い 投票DB はそのまま DROP、もしくは一定期間保存/ファイルに書き出して DROP 。

キモは、下手に 投票DB 上で DELETE / Optimize 等の操作を行うよりは、新たに TABLE を作り直した方が速いことと、sub key を付けておくと count が速いことです(keyがメモリに全て乗っていれば)。また、投票DB には(おそらく)全ての 商品DB.商品ID は乗らないであろうことが期待出来ることです(mysql/innodb の前提で記載しています)。

# 一番簡単なのは 投票DB はオンメモリで持って(定時ファイル書き出し等と併用) した上で、 投票数だけ SQL サーバで管理しなくて KVS にぶち込むことだと思いますが(商品DB の UPDATE 回数を避けるため)。

対象としている商品数、単位時間あたりの投票数・DBサーバのキャパシティが解らないのでざっくりとした回答しかできませんが参考になれば。

id:black_kenchan

とても参考になりました。

本当に有難う御座います。

2010/11/22 12:46:01

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません