web-dev-qa-db-ja.com

Facebookデータベースの設計?

私は、Facebookがどのようにして友人<->ユーザー関係を設計したのかといつも思っていました。

ユーザーテーブルは次のようなものだと思います。

user_email PK
user_id PK
password 

ユーザーデータ(性別、年齢など、想定されるユーザーの電子メールを介して接続されている)を含むテーブルを作成します。

すべての友達をこのユーザーにどのように接続しますか?

このようなもの?

user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N 

おそらくない。ユーザー数が不明であり、拡大するためです。

129
Marin

UserIDを保持するfriendテーブルを保持し、次に友人のUserIDを保持します(FriendIDと呼びます)。両方の列は、Usersテーブルに戻る外部キーになります。

やや便利な例:

Table Name: User
Columns:
    UserID PK
    EmailAddress
    Password
    Gender
    DOB
    Location

TableName: Friends
Columns:
    UserID PK FK
    FriendID PK FK
    (This table features a composite primary key made up of the two foreign 
     keys, both pointing back to the user table. One ID will point to the
     logged in user, the other ID will point to the individual friend
     of that user)

使用例:

Table User
--------------
UserID EmailAddress Password Gender DOB      Location
------------------------------------------------------
1      [email protected]  bobbie   M      1/1/2009 New York City
2      [email protected]  jonathan M      2/2/2008 Los Angeles
3      [email protected]  joseph   M      1/2/2007 Pittsburgh

Table Friends
---------------
UserID FriendID
----------------
1      2
1      3
2      3

これは、ボブがジョンとジョーの両方の友人であり、ジョンもジョーの友人であることを示します。この例では、友情は常に2つの方法であると仮定します。したがって、テーブル内に(2,1)や(3,2)などの行は必要ありません。友情や他の関係が明示的に双方向でない場合の例については、双方向の関係を示すためにそれらの行も必要です。

88
TheTXI

次のデータベーススキーマ Anatoly Lubarskyによって作成されたリバース をご覧ください。

Facebook Schema

49
Simon

TL; DR:

スタックのMySQLボトムより上にあるすべてのものに対して、キャッシュされたグラフを持つスタックアーキテクチャを使用します。

ロングアンサー:

膨大な量のデータをどのように処理し、迅速に検索するのか興味があったので、このことについて自分で調査しました。ユーザーベースが拡大すると、カスタムメイドのソーシャルネットワークスクリプトが遅くなることについて不満を言う人を見てきました。 ちょうど10kユーザーと250万人の友人でベンチマークを行った後接続-グループの許可やいいね、壁の投稿を気にすることさえしません-このアプローチには欠陥があることがすぐにわかりました。だから、私はそれを改善する方法についてウェブを検索するのにいくらか時間を費やし、この公式のFacebookの記事に出くわしました:

Ireally読み続ける前に、上記の最初のリンクのプレゼンテーションを見ることをお勧めします。これはおそらく、FBが背後でどのように機能するかについての最良の説明です。

ビデオと記事では、いくつかのことを説明しています。

  • 彼らはスタックのまさにbottomでMySQLを使用しています
  • AboveSQL DBには、少なくとも2つのレベルのキャッシングを含み、グラフを使用して接続を記述するTAO層があります。
  • キャッシュされたグラフに実際に使用しているソフトウェア/ DBについては何も見つかりませんでした

これを見てみましょう。友達とのつながりは左上です。

enter image description here

まあ、これはグラフです。 :) SQLでビルドする方法はhowではありませんが、それを行う方法はいくつかありますが、 このサイト にはかなりの違いがありますアプローチ。 注意:リレーショナルDBがそれであると考えてください:グラフ構造ではなく、正規化されたデータを保存することを考えています。そのため、専用のグラフデータベースほど優れたパフォーマンスは得られません。

また、友人の友人よりも複雑なクエリを実行する必要があることも考慮してください。たとえば、あなたと友人の友人が好きな特定の座標の周りのすべての場所をフィルタリングする場合です。ここではグラフが完璧なソリューションです。

うまく機能するように構築する方法を説明することはできませんが、明らかに試行錯誤とベンチマークが必要です。

ここに私のがっかりしたjust友達の友達を見つけるためのテスト:

DBスキーマ:

CREATE TABLE IF NOT EXISTS `friends` (
`id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `friend_id` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

Friends of Friendsクエリ:

(
        select friend_id
        from friends
        where user_id = 1
    ) union (
        select distinct ff.friend_id
        from
            friends f
            join friends ff on ff.user_id = f.friend_id
        where f.user_id = 1
    )

少なくとも1万人のユーザーレコードを持つサンプルデータを作成し、各レコードに少なくとも250人の友人の接続があるようにしてから、このクエリを実行することをお勧めします。私のマシン(i7 4770k、SSD、16GB RAM)では、そのクエリの結果は〜0.18秒でした。最適化できるかもしれませんが、私はDBの天才ではありません(提案を歓迎します)。ただし、ifこれは、すでに100,000人のユーザーに対して1.8秒、100万人のユーザーに対して18秒で線形にスケーリングします。

〜10万人のユーザーにとってはこれで問題ないように聞こえるかもしれませんが、友達の友達を取得したばかりで、「友達の友達からの投稿のみを表示し、それらのいくつかを見ることが許可されているか許可されていないか、サブクエリを実行して、それらのいずれかが好きかどうかを確認します)。すでに投稿が気に入ったかどうか、またはコードで行う必要がある場合、DBにチェックを行わせたいと思います。また、これがあなたが実行する唯一のクエリではなく、多かれ少なかれ人気のあるサイトで同時にアクティブなユーザーがいることを考慮してください。

私の答えは、Facebookが彼らの友人関係をどのように設計したかという質問に答えていると思いますが、それが迅速に機能する方法でそれを実装する方法を伝えることができないのは残念です。ソーシャルネットワークの実装は簡単ですが、それがうまく機能することを確認することは明らかにそうではありません-私見。

OrientDBを使用してグラフクエリを実行し、エッジを基になるSQL DBにマッピングし始めました。完了したら、それについての記事を書きます。

42
burzum

私の最善の策は、彼らが グラフ構造 を作成したことです。ノードはユーザーであり、「フレンドシップ」はエッジです。

1つのユーザーテーブルを保持し、別のエッジテーブルを保持します。その後、「友達になった日」や「承認済みのステータス」など、エッジに関するデータを保持できます。

32

ほとんどの場合、多対多の関係です。

FriendList(テーブル)

user_id -> users.user_id
friend_id -> users.user_id
friendVisibilityLevel

編集

ユーザーテーブルには、おそらくPKとしてuser_emailがなく、おそらく一意のキーとしてがあります。

ユーザー(表)

user_id PK
user_email
password
20
Nathan Koop

LinkedInとDiggの構築方法を説明している以下の記事をご覧ください。

「ビッグデータ:Facebookデータチームからの視点」も役立ちます。

http://developer.yahoo.net/blogs/theater/archives/2008/01/nextyahoonet_big_data_viewpoints_from_the_fac.html

また、非リレーショナルデータベースと、一部の企業によるそれらの使用方法について説明している次の記事があります。

http://www.readwriteweb.com/archives/is_the_relational_database_doomed.php

これらの企業は、データウェアハウス、パーティション化されたデータベース、データキャッシング、および私たちのほとんどが日常的に扱っていない他のより高いレベルの概念を扱っていることがわかります。または、少なくとも、私たちがそうすることを知らないかもしれません。

最初の2つの記事には、より多くの洞察を提供する多くのリンクがあります。

UPDATE 10/20/2014

Murat Demirbas に要約を書いた

  • TAO:Facebookのソーシャルグラフ用の分散データストア(ATC'13)
  • F4:FacebookのウォームBLOBストレージシステム(OSDI'14)

http://muratbuffalo.blogspot.com/2014/10/facebooks-software-architecture.html

HTH

16

一定の時間に5億を超えるデータのユーザーフレンドデータのRDBMSからデータを取得することはできないため、Facebookはハッシュデータベース(SQLなし)を使用してこれを実装し、Cassandraというデータベースをオープンソース化しました。

したがって、すべてのユーザーが独自のキーと友人の詳細をキューに入れています。 cassandraがどのように機能するかを知るには、これを見てください:

http://prasath.posterous.com/cassandra-55

9
user362541

この最近の2013年6月の投稿では、関係データベースから一部のデータ型の関連付けを持つオブジェクトへの移行について詳しく説明しています。

https://www.facebook.com/notes/facebook-engineering/tao-the-power-of-the-graph/1015152598399392

Https://www.usenix.org/conference/atc13/tao-facebook’s-distributed-data-store-social-graphに長い論文があります

6

外部キーを探しています。基本的に、独自のテーブルがない限り、データベースに配列を持つことはできません。


スキーマの例:

ユーザーテーブル
 userID PK 
その他のデータ
フレンドテーブル
 userID-フレンドを持つユーザーを表すユーザーのテーブルへのFK。
 friendID-友人のユーザーIDを表すユーザーテーブルへのFK
5
Malfist

そのタイプのグラフデータベース: http://components.neo4j.org/neo4j-examples/1.2-SNAPSHOT/social-network.html

リレーショナルデータベースとは関係ありません。

グラフデータベース用のGoogle。

4
zain

データベーステーブルは、水平方向(列数)ではなく、垂直方向(行数)に拡大するように設計されていることに注意してください。

2
Neil N

おそらく、友人 '->ユーザーリレーション、たとえば "frnd_list"を格納するテーブルがあり、フィールド' user_id '、' frnd_id 'があります。

ユーザーが別のユーザーを友達として追加するたびに、2つの新しい行が作成されます。

たとえば、IDが 'deep9c'で、IDが 'akash3b'のユーザーを友達として追加すると、テーブル(frnd_list)に値( 'deep9c'、 'akash3b')および( 'akash3b)を持つ2つの新しい行が作成されます'、' deep9c ')。

特定のユーザーにフレンドリストを表示する場合、単純なsqlで次のようになります。

0
deep9c

多対多テーブルのパフォーマンスに関して、ユーザーIDをリンクする32ビットintが2つある場合、平均200人の友人の200,000,000ユーザーの基本データストレージはそれぞれ300GB未満です。

明らかに、パーティション化とインデックス作成が必要になりますが、それをすべてのユーザーのメモリに保持するわけではありません。

0
Cade Roux