2013-11-01 24 views
6

私のウェブサイトにはフォロワー/以下のシステムがあります(Twitterのようなものです)。私のジレンマは、誰が誰に従うのかを処理するデータベース構造を作成することです。私はこのような表を作成していた思い付いた何フォロワー/フォローしているデータベース構造

id | user_id | followers | following 
    1 | 20  | 23,58,84 | 11,156,27 
    2 | 21  | 72,35,14 | 6,98,44,12 
... | ...  | ...  |  ... 

基本的に、私は、各ユーザーが自分のフォロワーと、彼らがフォローしているユーザーのための列と行を持っているだろうと考えていました。フォロワーとフォローしているユーザーは、ユーザーIDをカンマで区切ります。

これは効果的な方法ですか?そうでない場合、最良の選択肢は何ですか?

ありがとうございました。

答えて

19

これは最悪の方法です。それは正規化に反する。 2つのテーブルを用意してください。ユーザーとユーザー_フォルダー。ユーザーはユーザー情報を保管します。 User_Followersは次のようになります。

id | user_id | follower_id 
1 | 20  | 45 
2 | 20  | 53 
3 | 32  | 20 

USER_IDとFollower_Idのユーザーテーブルのidカラムを参照する外部キーになります。

+0

ええ、それは私が思いついた2番目の構造でしたが、これを行うのが慣例ではないと思っていました。ありがとう。 – Burrows

+2

私は*正規化が過去のものだと思った。あなたはおそらく* Oracle *のために働きます。 – Vad

+1

@Vad私はオラクルではうまくいきません:)正規化はリレーショナルDBシステムとデータの概念です。これらのシステムが生存していれば、それは過去のものではありません:) – regulus

4

この表現の弱点の1つは、各関係がフォロワー用に1回、次のユーザー用に1回、2回エンコードされるため、データの整合性と更新が困難になります。

私は、ユーザー用のテーブルとリレーションシップ用のテーブルを作成します。リレーションシップテーブルは次のようになります。

id | follower | following 
1 | 23  | 20 
2 | 58  | 20 
3 | 84  | 20 
4 | 20  | 11 
... 

このように新しいリレーションシップを追加すると、リレーションシップを削除するだけで済みます。また、カウントをロールアップして、特定のユーザーのフォロワー数を判断する方がはるかに簡単です。

1

いいえ、あなたのアプローチにはいくつかの問題があります。

まず、複数のデータポイントをカンマ区切り文字列として格納することにはいくつかの問題があります。参加することは困難です(また、likeを使用すると参加できますが、パフォーマンスが低下します)、検索が困難で遅くなり、必要な方法でインデックスに登録することはできません。

第2に、フォロワーのリストとフォロワーのリストの両方を保存すると、余分なデータがあります(AがBに続くという事実は2つの場所に現れます)。同期が外れてデータが潜在する可能性もあります(データベースにAのBのフォロワーのリストが表示され、BのAのフォローのリストは表示されない場合、データは回復しにくい方法で矛盾します)。

代わりに、結合テーブルを使用してください。これは、各行がユーザーIDとフォロワーIDを持つ別のテーブルです。これにより、物事を1か所に保存し、索引付けと結合が可能になります。たとえば、次の関係がいつ開始されたかを示すために、列に追加の列を追加することもできます。

2

良く物理構造は、これまで他の答えが提案するよりもあります:

CREATE TABLE follower (
    user_id INT, -- References user. 
    follower_id INT, -- References user. 
    PRIMARY KEY (user_id, follower_id), 
    UNIQUE INDEX (follower_id, user_id) 
); 

InnoDBテーブルはclusteredあるので、セカンダリインデックスは、ヒープベースのテーブルでは異なる動作をしている場合、予期しないオーバーヘッドを持つことができますあなたはそのことを認識していません。代理主キーを持つidは、理由がないために別のインデックスを追加するだけですと{user_id、follower_id}および{follower_id、user_id}のインデックスを必要以上に太くします(クラスタ化テーブルの2次インデックスは暗黙的にコピーPKの)。

上記の表には、検索の場合とほぼ同じくらい効率的な、2つのBツリー(1次/クラスタリングキー用と2次インデックス用)で物理的に表現される(InnoDBと仮定して) idはありません。双方向で。一方向だけが必要な場合は、セカンダリインデックスを放棄して1つのBツリーに移動できます。

ところで、あなたがしたことは、atomicityの原則に違反し、したがって1NFの違反でした。


、すべての追加のインデックスは、スペースをとりINSERT/UPDATE/DELETEのパフォーマンスをキャッシュの有効性と影響を低下させます。

フォロワ及びその逆にフォロイーから。

関連する問題