페이스 북 데이터베이스 디자인?


133

나는 Facebook이 어떻게 친구 <-> 사용자 관계를 어떻게 설계했는지 궁금했습니다.

사용자 테이블이 다음과 같다고 생각합니다.

user_email PK
user_id PK
password 

나는 사용자의 데이터 (성별, 연령 등이 사용자 이메일을 통해 연결되어 있음)로 테이블을 계산합니다.

모든 친구를이 사용자와 어떻게 연결합니까?

이 같은?

user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N 

아마 아닙니다. 사용자 수를 알 수없고 확장되기 때문입니다.


13
이러한 유형의 정보가 많은 Facebook 엔지니어링 페이지가 있지만 원하는 것은 아닙니다. 당신은 거기에 물어보고 대답을 얻을 수 있는지 볼 수 있습니다. facebook.com/FacebookEngineering
John Meagher 2016 년

1
구글 graph database. 확실히 RDBMS 가 아닙니다 .

답변:


90

사용자 ID를 보유한 친구 테이블과 그 다음 친구의 사용자 ID를 유지하십시오 (이를 FriendID라고 함). 두 열 모두 사용자 테이블에 대한 외래 키입니다.

다소 유용한 예 :

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      bob@bob.com  bobbie   M      1/1/2009 New York City
2      jon@jon.com  jonathan M      2/2/2008 Los Angeles
3      joe@joe.com  joseph   M      1/2/2007 Pittsburgh

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

이것은 Bob이 Jon과 Joe의 친구이고 Jon이 Joe 와도 친구임을 나타냅니다. 이 예에서는 우정이 항상 두 가지 방법이라고 가정하므로 (2,1) 또는 (3,2)와 같은 행은 이미 다른 방향으로 표시되어 있으므로 행이 필요하지 않습니다. 우정 또는 기타 관계가 명시 적으로 양방향이 아닌 예의 경우 양방향 관계를 나타 내기 위해 해당 행도 있어야합니다.


8
이 방법이 얼마나 비효율적인지 생각해보십시오. 다 대다 열에서 평균적으로 두 배의 검색 시간에 대해 분리형 쿼리를 수행해야합니다.
Anthony Bishopric

2
개인적으로, 나는이 두 필드가 복합 기본 키를 만드는 것을 원하지 않습니다. 절대적으로 독특한 열쇠. 확실히 그 고유 키의 클러스터형 인덱스. 그러나 비 클러스터형 인덱스를 가진 일종의 비 복합 ID를 PK로 넣었습니다. 즉, "친구 관계 ID"FK 쉽게이 테이블에 묶어 다양한 트리거 등, 친구 맺기 defriending의 계단식 이벤트를 발사 할 수 필요한 다른 테이블 수있는 것
제시 C. 슬라이서

1
페이스 북은 약 1'000'000'000 명의 사용자가 있다고한다. 평균 사용자가 친구가 100 명인 경우 테이블에 100'000'000'000 개의 행이 포함됩니다. MySQL 파티셔닝?
veidelis

이 방법을 잊어 버리십시오. 당신이 사용자의 심각한 양을 얻을 경우 그것은 확실히 될 것입니다 매우 느리다. 내 대답을보고 직접 벤치마킹하십시오. 10k 사용자와 250 만 명의 우정 관계로 벤치마킹을 해 결과가 실망 스러웠습니다. 소규모 커뮤니티를 운영하는 경우 잘 작동하지만 고려해야 할 성능 문제가 있습니다.
burzum

7
당신은 페이스 북이 이것을 위해 RDBMS를 사용하지 않는다는 것을 확신 할 수 있습니다. 이와 같은 쿼리를 실행 해야하는 사람들, 트위터 및 다른 사람들은 어떤 풍미의 그래프 데이터베이스를 사용한다는 것이 일반적입니다. 어떤 종류의 규모로든 일한 적이 없거나 규모에서 수학을 수행하는 방법을 모르는 69 명 이상이 있습니다.

51

Anatoly Lubarsky가 리버스 엔지니어링 한 다음 데이터베이스 스키마를 살펴보십시오 .

페이스 북 스키마


7
이것은 데이터베이스 스키마가 아닌 클래스 다이어그램입니다
Lemon Juice

2
그렇다면 각 "사용자"는 전용 데이터베이스를 가지고 있습니까? 위의 것처럼? 어떻게 작동합니까? 예를 들어 사용자가 FB에 로그온하면 유효한 사용자 + 패스인지 확인한 다음 유효한 페이스
북인

이 스토어는 사용자와 관련된 정보 만 저장합니다. 특히 게시물과 대상을 검색하고 있습니까?
Waseem Ahmad Naeem

47

TL; DR :

이들은 스택의 MySQL 맨 위에있는 모든 것에 대해 캐시 된 그래프가있는 스택 아키텍처를 사용합니다.

긴 답변 :

나는 그들이 방대한 양의 데이터를 처리하고 빠른 방법으로 검색하는 방법이 궁금하기 때문에 이것에 대해 약간의 연구를했습니다. 사용자 기반이 커지면 맞춤형 소셜 네트워크 스크립트가 느려지는 것에 대해 불평하는 사람들이 있습니다. 그룹 권한과 좋아요 및 벽 게시물에 대해 신경 쓰지 않고 10k 명의 사용자와 250 만 명의 친구 연결로 벤치마킹 한 후이 접근법에 결함이 있음이 신속하게 밝혀졌습니다. 그래서 웹을 더 잘하는 방법에 대해 웹을 검색하는 데 시간을 보냈 으며이 공식 Facebook 기사를 보았습니다.

나는 정말 전에 계속 읽고 위의 첫 번째 링크의 프레젠테이션을보고 당신을 추천합니다. FB가 찾을 수있는 장면에서 어떻게 작동하는지에 대한 최고의 설명 일 것입니다.

비디오와 기사는 몇 가지 사항을 알려줍니다.

  • 그들은 스택 맨 아래 에서 MySQL을 사용 하고 있습니다.
  • SQL DB 위에는 적어도 두 가지 수준의 캐싱을 포함하고 연결을 설명하기 위해 그래프를 사용하는 TAO 계층이 있습니다.
  • 캐시 된 그래프에 실제로 사용하는 소프트웨어 / DB에서 아무것도 찾을 수 없습니다.

이걸 보자. 친구 연결은 왼쪽 상단입니다.

여기에 이미지 설명을 입력하십시오

글쎄, 이것은 그래프입니다. :) SQL로 작성 하는 방법 을 알려주지는 않지만 여러 가지 방법 있지만 이 사이트 에는 많은 다른 접근 방식이 있습니다. 주의 : 관계형 DB가 무엇인지 고려하십시오. 그래프 구조가 아니라 정규화 된 데이터를 저장하는 것으로 생각됩니다. 따라서 특수 그래프 데이터베이스만큼 성능이 좋지 않습니다.

또한 예를 들어 친구와 친구가 좋아하는 특정 좌표 주위의 모든 위치를 필터링하려는 경우 친구의 친구보다 복잡한 쿼리를 수행해야합니다. 그래프는 완벽한 솔루션입니다.

제대로 작동하도록 빌드하는 방법을 알 수는 없지만 시행 착오와 벤치마킹이 분명히 필요합니다.

여기 내입니다 실망 에 대한 시험 단지 친구의 결과 친구 :

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;

친구의 친구 쿼리 :

(
        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
    )

최소한 10k 이상의 사용자 레코드로 샘플 데이터를 작성하고 각각 250 명 이상의 친구 연결을 가지고이 쿼리를 실행하는 것이 좋습니다. 내 컴퓨터 (i7 4770k, SSD, 16gb RAM)에서 해당 쿼리 의 결과는 ~ 0.18 초 였습니다. 어쩌면 그것은 DB 천재가 아닙니다 (제안은 환영합니다). 그러나이 스케일이 선형 이면 1 억 명의 사용자의 경우 이미 1.8 초, 백만 명의 사용자의 경우 18 초입니다.

~ 100k 명의 사용자에게는 여전히 괜찮은 것처럼 들릴 수 있지만 친구의 친구를 가져 왔으며 " 친구의 친구에게만 게시 한 게시물 표시 + 허용 여부에 대한 권한 확인 수행 "과 같이 더 복잡한 쿼리를 수행하지 않았다고 생각하십시오 그들 중 일부를보고 + 내가 그들 중 하나를 좋아하는지 확인하기 위해 하위 쿼리를 수행 ". 게시물이 이미 좋았는지 아닌지 또는 코드를 작성해야하는지 DB가 확인하도록하려고합니다. 또한이 쿼리 만이 실행되는 쿼리는 아니며 인기있는 사이트에서 동시에 활성 사용자보다 많은 사용자가 있다는 것을 고려하십시오.

내 대답은 Facebook이 친구 관계를 어떻게 잘 설계했는지에 대한 질문에 대한 답변이라고 생각하지만 빠른 작동 방식으로 구현하는 방법을 말할 수 없어서 죄송합니다. 소셜 네트워크를 구현하는 것은 쉽지만 제대로 작동하는지 확인하는 것은 분명하지 않습니다-IMHO.

그래프 쿼리를 수행하고 가장자리를 기본 SQL DB에 매핑하기 위해 OrientDB를 실험하기 시작했습니다. 내가 끝내면 그것에 관한 기사를 쓸 것입니다.


그래서 .. 당신은 기사를 쓰기 위해 돌아왔습니까?
FlowUI. SimpleUITesting.com

1
아니요, 저는 프로그래밍을하는 것 외에는 바쁘고 그렇게 할 시간과 분위기가 없었습니다. 여기에 답에는 공연 친구 연합을 구현하려는 경우 알아야 할 모든 것이 포함되어 있습니다. 사용자 당 프렌드리스트를 캐시하거나 관계형 DB를 부분 또는 전체로 그래프에 매핑하고 그래프 DB를 쿼리하십시오. 이를 위해 OrientDB 또는 Neo4j를 사용할 수 있습니다. 나는 나 자신의 오픈 소스 소셜 네트워킹 소프트웨어를 작성하고 싶지만 다른 많은 것들도 있습니다. 무엇을하든 : 벤치 마크를 수행하십시오. :)
burzum

아직도 아니야. 그러나 OrientDB 설명서는 친구 연결을 설명하고 기본 사항을 이해하면 다른 모든 것을 모델링 할 수 있습니다. orientdb.com/docs/2.1/Tutorial-Working-with-graphs.html 관계형 DB를 기초로 사용하려면 "저장 후"및 "삭제 후"콜백에 코드를 추가하면 그래프 DB (데이터를 읽는 데 사용). 그러한 콜백이 구현되지 않으면 거의 모든 종류의 ORM 구현 및 프레임 워크에 이와 비슷한 것이 있다고 생각합니다. 실제로 OrientDB는 문서도 저장할 수 있습니다.
burzum

1
그래서 .. 당신은 기사를 쓰기 위해 돌아왔습니까?
코너 거니

1
그래도 우리는 직장에서 비슷한 일을합니다. 우리는 관계형 데이터를 Elastic Search 인덱스에 매핑합니다. (이 경우에는 afterSave () / afterDelete () 콜백)하고 인덱스 또는 그래프를 업데이트하십시오. 꽤 간단합니까? :) 그런데 친구 목록에서도 동일하게 수행 할 수 있습니다 (ESM, 그래프 또는 메모리 기반 캐시에 충분한 RAM이있는 한). 정말 어렵지는 않습니다. 어려운 부분은 성장할 때 모든 것을 확장시키는 것입니다.
burzum

32

가장 좋은 방법은 그래프 구조 를 만드는 것 입니다 . 노드는 사용자이고 "우정"은 경계입니다.

한 사용자 테이블을 유지하고 다른 가장자리 테이블을 유지하십시오. 그런 다음 "친구가 된 날"및 "승인 된 상태"등 가장자리에 대한 데이터를 유지할 수 있습니다.


40
나는 여기에 어떤 사람들에게 조금 더 설명해야 할 느낌이 있습니다.
TheTXI 2016 년

4
더 흥미로운 질문은 쉽게 검색하고 업데이트 할 수있는 방식으로 거대한 구조 (약 2 억 개의 노드와 수십억 개의 에지)를 유지하는 방법에 대한 것입니다.
Dirk Vollmar 2016 년

1
@ divo : 인덱스와 파티션을 영리하게 사용합니다.
belgariontheking 2016 년

20

다 대다 관계 일 가능성이 높습니다.

친구 목록 (테이블)

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

편집하다

사용자 테이블에는 아마도 user_email이 PK로, 아마도 고유 키로 없을 수 있습니다 .

사용자 (테이블)

user_id PK
user_email
password

4
이것이 가장 의미가 있지만 Facebook 사용자 수와 Facebook 사용자 수를 감안할 때 성능이 끔찍하다고 생각합니다.
Kevin Pang

17

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

이 회사들이 대부분의 사람들이 매일 다루지 않는 것보다 데이터웨어 하우스, 파티션 된 데이터베이스, 데이터 캐싱 및 기타 높은 수준의 개념을 다루고 있음을 알 수 있습니다. 아니면 적어도 우리는 우리가 모르는 것 같습니다.

처음 두 기사에는 더 많은 통찰력을 제공하는 많은 링크가 있습니다.

2014 년 10 월 20 일 업데이트

Murat Demirbas 는 다음에 대한 요약을 작성했습니다.

  • TAO : 소셜 그래프를위한 Facebook의 분산 데이터 저장소 (ATC'13)
  • F4 : Facebook의 따뜻한 BLOB 저장 시스템 (OSDI'14)

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

HTH


9

일정 시간에 50 억이 넘는 데이터에 대한 사용자 친구 데이터를 위해 RDBMS에서 데이터를 검색 할 수 없으므로 Facebook은 해시 데이터베이스 (SQL 없음)를 사용하여이를 구현하고 Cassandra라는 데이터베이스를 오픈 소스 화했습니다.

따라서 모든 사용자에게는 고유 한 키와 친구 세부 정보가 대기열에 있습니다. cassandra가 어떻게 작동하는지 알고 싶다면

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


매우 흥미 롭습니다. 제 친구 감사합니다. 그들은 SQL에서 cassandra로 언제 전환 했습니까? 당신은 알고 있습니까?
Marin

1
알아두기 : Posterous Spaces는 죽었다. 그래서 링크.
TechNyquist


5

외래 키를 찾고 있습니다. 기본적으로 자체 테이블이 없으면 데이터베이스에 배열을 가질 수 없습니다.


스키마 예 :

    사용자 테이블
        userID PK
        다른 데이터
    친구 테이블
        userID-친구가있는 사용자를 나타내는 사용자 테이블에 대한 FK.
        friendID-친구의 사용자 ID를 나타내는 FK to Users 테이블

5
왜 다운 보트인가? 적어도 왜 당신이 그들에게 하향 투표를했는지 알려주십시오.
Sasha Chedygov

3
@freak : 왜? 이 사이트에서 투표의 전체 개념은 익명의 투표입니다. 왜 Malfist에게 어떤 권리가 있다고 생각합니까?
GEOCHET

4
특히 그것이 정답이고 다른 답에 의해 반향 될 때 (응답을 할 때 답을 찾을 수 없지만 답을 찾을 수없는 곳)
Malfist

4
@TheTXI : 다운 보트에 대한 의견은 특히 호의적이지 않은 답변에 대한 예의라고 생각하지만, 의견에 대한 의무는 없습니다.
Robert S.

2
불명확 한 답변에 익명으로 폭행 한 사람들은 폭행을 설명하는 의견을 남겼다면 얕은 추론이 노출 될까봐 두려워하는 사람들입니다.
Vinayak


1

데이터베이스 테이블은 수평이 아닌 수직으로 확장되도록 설계되었습니다 (열이 더 많음).


24
절대 잊지 마세요! 아빠는 열에 대해 너무 수직으로 커진 db 테이블로 인해 사망했습니다. 아빠보고 싶어요
belgariontheking 2016 년

1
흠, 왜 downvote? 그리고 위의 의견은 의미가 없습니다.
Neil N

2
아니요, 의견이 이해가되지 않습니다. 누군가 웃기려고했던 것처럼 보이므로 걱정하지 마십시오.
Dirk Vollmar 2016 년

0

다 대다 테이블의 성능과 관련하여 사용자 ID를 연결하는 2 개의 32 비트 정수가있는 경우 각각 200 명의 친구를 평균하는 200,000,000 명의 사용자를위한 기본 데이터 스토리지는 300GB 미만입니다.

분명히, 일부 파티셔닝 및 인덱싱이 필요하며 모든 사용자를 위해 메모리에 보관하지 않을 것입니다.


0

아마도 'user_id', 'frnd_id'필드를 가진 "frnd_list"와 같은 친구 <-> 사용자 관계를 저장하는 테이블이있을 것입니다.

사용자가 다른 사용자를 친구로 추가 할 때마다 두 개의 새 행이 작성됩니다.

예를 들어, ID가 'deep9c'이고 ID가 'akash3b'인 친구를 내 친구로 추가 한 다음 테이블 "frnd_list"에 값 ( 'deep9c', 'akash3b') 및 ( 'akash3b ','deep9c ').

이제 특정 사용자에게 친구 목록을 표시 할 때 간단한 sql은 다음과 같이 수행합니다. "frnd_list에서 frnd_id 선택.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.