2009-03-06 7 views
4

私は現在、PHP/MySQLレーティングシステムを開発中です。ユーザーがログインする必要があることをユーザーが評価できるようにするために、各ユーザーには一意の「UID」があります。ウェブサイトには複数の格付けインスタンスがあります(私の場合はすべてのゲームに1つずつ)、私はMySQLの行にUIDのリストを格納する効率的な方法が必要です(格付けシステムの各インスタンス)投票した人の集計を保持する。ユーザIDのリストを保存するための最良の方法

他のシステムでは、リストがシリアル化されたPHP配列に格納されています。ユーザーが投票するたびに、シリアライズされた配列が抽出され、シリアル化されず、新しいUIDが挿入され、配列が再シリアル化され、MySQL行がUPDATEされます。ページがロードされるたびに、そのリストを再度シリアル化してチェックして、ページを閲覧しているユーザーがまだ投票していないかどうかを確認する必要があります。

これは非効率的で面倒なようです。このプロセスをより効率的にするために、MySQLにリスト機能が組み込まれていますか?この問題を解決するためのもっと巧妙な方法はありますか?

私は、シリアライズを忘れて、UIDをMySQLデータベースのTEXT型フィールドに格納する可能性のある代替案を検討しました。私はちょうど各UIDの後にいくつかの非数字の文字を追加します(ピリオド[。])。ユーザーエントリを追加するには、UIDをTEXTフィールドの最後に連結し、次にピリオドを連結します。ユーザーがすでに投票しているかどうかを確認するときに、私はちょうど "* FROM table WHERE votes = '%$ UID。%';"というように選択できます。これはより効率的に機能するのでしょうか、それとも仕事を効率的にする方法がありますか?テーブル構造について

フォローアップのポスト...正規化されたデータベースでEfficient MySQL table structure for rating system

答えて

17

これは非効率的です。リレーショナルな言葉でここにあるのは、ユーザーとゲームの多対多の関係です。ユーザーは多くのゲームに投票することができます。多くのユーザーがゲームに投票することができます。これの解決策は、結合テーブルを持つことです。

USERS (uid, name, ...) 
GAMES (gid, name, ...) 
VOTES (id, uid, gid, ...) 

ここで、uidとgidは、それぞれのテーブルに戻ってくる外部キーです。

誰かが投票した場合、VOTESにレコードを挿入します。

ゲームのための投票のリストを取得するには:

$get = mysql_query("SELECT * FROM votes WHERE uid = $user_id"); 
... 

など:ユーザーの投票のリストを取得するには

$get = mysql_query("SELECT * FROM votes WHERE gid = $game_id"); 
... 

を。

アレイに参加して1列に格納しないでください。あなたはそれを避けるのは正しいです。

+0

あなたとメードラードは同じアプローチを提案しているようです。私はこのようにします。私の懸念は、VOTESテーブルのサイズです。おそらく、そのテーブルに<#games x#users>の投票権があると考えられます。それは私の共有ホスティングプランの管理者を恐れさせるべきでしょうか? –

+1

現実的には、「パーティション化」(基本的にデータの分割)を考慮する必要がある前に、テーブルサイズが何百万ものものになっている必要があります。配列を暗黙に埋めるアプローチは行を持ちますが、読み取りと書き込みの両方でかなり高いオーバーヘッドがあります。 – cletus

+1

上記のクエリを実行している場合は、* uidとgidの両方でテーブルのインデックスを作成して、クエリを高速化してください。これは、このアプローチの最大のペナルティです。複数のインデックスが必要です。 – slacy

4

、あなたはジャンクションテーブルに格納する必要があります。

UserRatings 
------------- 
RatingID int 
UserID int 
UserVote int 

私は何をしているかわかりませんあなたの質問。アプリケーションによっては、これは許容できるパフォーマンスを持たないかもしれません。しかし、どちらの場合でも、正規化されたアプローチ、ベンチマーク、非正規化は適切な場合にのみ行うことをお勧めします。

関連する問題