web-dev-qa-db-fra.com

Conception de la base de données Facebook?

Je me suis toujours demandé comment Facebook avait conçu la relation d’amitié <->.

Je suppose que la table des utilisateurs ressemble à ceci:

user_email PK
user_id PK
password 

Je figure la table avec les données de l'utilisateur (sexe, âge, etc., connectées via le courrier électronique de l'utilisateur, je suppose).

Comment relie-t-il tous les amis à cet utilisateur?

Quelque chose comme ça?

user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N 

Probablement pas. Parce que le nombre d'utilisateurs est inconnu et va augmenter.

129
Marin

Conservez une table d'amis contenant l'ID utilisateur, puis l'ID utilisateur de l'ami (nous l'appellerons FriendID). Les deux colonnes seraient des clés étrangères dans la table Utilisateurs.

Exemple quelque peu utile:

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)

Exemple d'utilisation:

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

Cela montrera que Bob est ami avec Jon et Joe et que Jon est également ami avec Joe. Dans cet exemple, nous supposerons que l'amitié est toujours à double sens, vous n'avez donc pas besoin d'une ligne dans la table telle que (2,1) ou (3,2) car elles sont déjà représentées dans l'autre sens. Pour des exemples où l'amitié ou d'autres relations ne sont pas explicitement à double sens, vous devez également avoir ces lignes pour indiquer la relation à double sens.

88
TheTXI

Regardez le schéma de base de données suivant, reverse engineering par Anatoly Lubarsky :

Facebook Schema

49
Simon

TL; DR:

Ils utilisent une architecture de pile avec des graphiques en cache pour tout ce qui se trouve au-dessous du bas MySQL de leur pile.

Réponse longue:

J'ai moi-même fait des recherches à ce sujet, car j'étais curieux de savoir comment ils géraient leur énorme quantité de données et les cherchaient rapidement. J'ai vu des gens se plaindre de la lenteur avec laquelle les scripts de réseaux sociaux fabriqués sur mesure se développaient lorsque la base d'utilisateurs grandissait. Après avoir fait quelques essais comparatifs avec seulement 10k utilisateurs et 2,5 millions d’amis connexions - ne même pas essayer de se soucier des autorisations de groupe et aime et posts du mur - il s'est vite avéré que cette approche est imparfaite. J'ai donc passé un certain temps à chercher sur le Web la meilleure façon de le faire et je suis tombé sur cet article officiel de Facebook:

Je vraiment Je vous recommande de regarder la présentation du premier lien ci-dessus avant de poursuivre la lecture. C'est probablement la meilleure explication du fonctionnement de FB dans les coulisses.

La vidéo et l'article vous disent quelques choses:

  • Ils utilisent MySQL même en bas de leur pile
  • Au-dessus La base de données SQL contient la couche TAO qui contient au moins deux niveaux de mise en cache et utilise des graphiques pour décrire les connexions.
  • Je ne trouvais rien sur les logiciels/bases de données qu'ils utilisaient pour leurs graphiques en cache

Jetons un coup d'oeil à ceci, les connexions d'amis sont en haut à gauche:

enter image description here

Eh bien, ceci est un graphique. :) Cela ne vous dit pas comment de le construire en SQL, il y a plusieurs façons de le faire mais ce site a une bonne quantité d'approches différentes. Attention: Considérez qu’une base de données relationnelle est ce qu’elle est: elle est conçue pour stocker des données normalisées, pas une structure graphique. Donc, il ne fonctionnera pas aussi bien qu'une base de données graphique spécialisée.

Pensez également que vous devez faire des requêtes plus complexes que juste des amis d'amis, par exemple lorsque vous souhaitez filtrer tous les emplacements autour d'une coordonnée donnée que vous et vos amis d'amis aimez. Un graphique est la solution parfaite ici.

Je ne peux pas vous dire comment le construire pour qu'il fonctionne bien, mais cela nécessite clairement des essais et des erreurs ainsi que des analyses comparatives.

Voici mon test décevant pour juste résultats amis d'amis:

Schéma de base de données:

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;

Les amis des amis interrogent:

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

Je vous recommande vivement de créer des exemples de données avec au moins 10 000 enregistrements d'utilisateurs et chacun d'eux ayant au moins 250 connexions d'amis, puis d'exécuter cette requête. Sur ma machine (i7 4770k, SSD, 16 Go de RAM), le résultat était ~ 0,18 seconde pour cette requête. Peut-être que cela peut être optimisé, je ne suis pas un génie de la base de données (les suggestions sont les bienvenues). Cependant, si cette échelle linéaire, vous êtes déjà à 1,8 secondes pour seulement 100 000 utilisateurs, 18 secondes pour 1 million d'utilisateurs.

Cela peut encore paraître OK pour environ 100 000 utilisateurs, mais considérez que vous venez de chercher des amis d'amis sans faire de requête plus complexe comme " affichez-moi uniquement les messages d'amis de amis d'amis + vérifiez si vous êtes bien autorisé." autorisé ou NON autorisé à voir certains d'entre eux + faire une sous-requête pour vérifier si j'ai aimé l'un d'entre eux ". Vous voulez laisser la base de données vérifier si vous avez déjà aimé ou non un message ou si vous devez le faire dans le code. Notez également que ce n’est pas la seule requête que vous exécutez et que vous avez plus qu’un utilisateur actif à la fois sur un site plus ou moins populaire.

Je pense que ma réponse répond à la question de savoir comment Facebook a très bien conçu la relation de leurs amis, mais je suis désolé de ne pas pouvoir vous dire comment la mettre en œuvre de manière à ce que cela fonctionne rapidement. La mise en place d'un réseau social est facile, mais il est clair que s'assurer de son bon fonctionnement - IMHO.

J'ai commencé à expérimenter avec OrientDB pour effectuer les requêtes graphiques et mapper mes arêtes sur la base de données SQL sous-jacente. Si jamais je réussis, j'écrirai un article à ce sujet.

42
burzum

Mon meilleur pari est qu'ils ont créé un structure graphique . Les nœuds sont des utilisateurs et les "amitiés" sont des arêtes.

Conservez une table d'utilisateurs, conservez une autre table d'arêtes. Ensuite, vous pouvez conserver des données sur les contours, comme "jour où ils sont devenus amis" et "statut approuvé", etc.

32
belgariontheking

C'est très probablement une relation plusieurs à plusieurs:

FriendList (table)

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

EDIT

La table utilisateur n'a probablement pas user_email en tant que PK, éventuellement en tant que clé unique.

utilisateurs (tableau)

user_id PK
user_email
password
20
Nathan Koop

Jetez un coup d’œil à ces articles décrivant la construction de LinkedIn et Digg:

Il y a aussi "Big Data: Points de vue de l'équipe de données Facebook" qui pourrait être utile:

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

En outre, cet article traite des bases de données non relationnelles et de leur utilisation par certaines entreprises:

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

Vous verrez que ces sociétés traitent avec des entrepôts de données, des bases de données partitionnées, la mise en cache de données et d'autres concepts de niveau supérieur que la plupart d'entre nous ne traitons jamais quotidiennement. Ou du moins, peut-être que nous ne le savons pas.

Il existe de nombreux liens sur les deux premiers articles qui devraient vous donner plus de perspicacité.

UPDATE 10/20/2014

Murat Demirbas a écrit un résumé sur

  • TAO: le magasin de données distribué de Facebook pour le graphe social (ATC'13)
  • F4: le système de stockage BLOB chaud de Facebook (OSDI'14)

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

HTH

16
Adrian J. Moreno

Il n'est pas possible de récupérer des données à partir du SGBDR pour les amis de l'utilisateur pour des données dépassant un demi-milliard de dollars en un temps constant. Facebook a donc implémenté cela à l'aide d'une base de données de hachage (pas de code SQL) et a ouvert la base de données appelée Cassandra.

Donc, chaque utilisateur a sa propre clé et les détails des amis dans une file d'attente; pour savoir comment cassandra fonctionne, regardez ceci:

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

9
user362541

Ce récent article de juin 2013 explique en détail la transition des bases de données relationnelles en objets avec des associations pour certains types de données.

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

Un article plus long est disponible à l'adresse https://www.usenix.org/conference/atc13/tao-facebook’s-distributed-data-stata-store-social-graph.

6

Vous recherchez des clés étrangères. Fondamentalement, vous ne pouvez pas avoir un tableau dans une base de données à moins qu'il ne possède sa propre table.


Exemple de schéma:

 Tableau des utilisateurs 
 ID utilisateur PK 
 Autres données 
 Tableau des amis 
 ID utilisateur - FK dans le tableau des utilisateurs représentant l'utilisateur ayant un ami. ____.] friendID - FK en table des utilisateurs représentant l'ID utilisateur de l'ami
5
Malfist

C'est un type de base de données de graphes: http://components.neo4j.org/neo4j-examples/1.2-SNAPSHOT/social-network.html

Ce n'est pas lié aux bases de données relationnelles.

Google pour les bases de données graphiques.

4
zain

Gardez à l'esprit que les tables de base de données sont conçues pour croître verticalement (plus de lignes), pas horizontalement (plus de colonnes)

2
Neil N

Il existe probablement une table qui stocke la relation amie <->, par exemple "frnd_list", contenant les champs "user_id", "frnd_id".

Chaque fois qu'un utilisateur ajoute un autre utilisateur en tant qu'ami, deux nouvelles lignes sont créées.

Par exemple, supposons que mon identifiant est "deep9c" et que j'ajoute un utilisateur ayant pour identifiant "akash3b", puis deux nouvelles lignes sont créées dans la table "frnd_list" avec les valeurs ("deep9c", "akash3b") et ("akash3b" ',' deep9c ').

Maintenant, lors de l'affichage de la liste d'amis à un utilisateur particulier, un simple SQL ferait cela: "select frnd_id à partir de frnd_list où user_id =" où est l'identifiant de l'utilisateur connecté (stocké en tant qu'attribut de session).

0
deep9c

En ce qui concerne les performances d'une table plusieurs-à-plusieurs, si vous avez 2 ints 32 bits liant des ID utilisateur, votre stockage de données de base pour 200 000 000 utilisateurs, avec une moyenne de 200 amis chacun, représente un peu moins de 300 Go.

De toute évidence, vous aurez besoin de partitionnement et d’indexation et vous ne garderez pas cela en mémoire pour tous les utilisateurs.

0
Cade Roux