Zawsze się zastanawiałem, w jaki sposób Facebook zaprojektował relację między przyjacielem a użytkownikiem.
Myślę, że tabela użytkowników wygląda mniej więcej tak:
user_email PK
user_id PK
password
Obliczam tabelę z danymi użytkownika (płeć, wiek itp. Połączonymi za pośrednictwem adresu e-mail użytkownika).
W jaki sposób łączy wszystkich znajomych z tym użytkownikiem?
Coś takiego?
user_id
friend_id_1
friend_id_2
friend_id_3
friend_id_N
Prawdopodobnie nie. Ponieważ liczba użytkowników jest nieznana i będzie się zwiększać.
graph database
. Na pewno nie jest to RDBMS.Odpowiedzi:
Zachowaj tabelę znajomych, która zawiera identyfikator użytkownika, a następnie identyfikator użytkownika znajomego (nazwiemy go FriendID). Obie kolumny byłyby kluczami obcymi z powrotem do tabeli Users.
Dość przydatny przykład:
Przykładowe zastosowanie:
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
To pokaże, że Bob jest przyjacielem zarówno Jona, jak i Joe, a Jon jest również przyjacielem Joe. W tym przykładzie założymy, że przyjaźń jest zawsze dwojakiego rodzaju, więc nie potrzebujesz wiersza w tabeli, takiego jak (2,1) lub (3,2), ponieważ są one już reprezentowane w innym kierunku. W przypadku przykładów, w których przyjaźń lub inne relacje nie są jawnie dwukierunkowe, należy również mieć te wiersze, aby wskazać relację dwukierunkową.
źródło
Spójrz na następujący schemat bazy danych, odtworzony przez Anatolija Lubarskiego :
źródło
TL; DR:
Używają architektury stosu z buforowanymi wykresami dla wszystkiego, co znajduje się powyżej dolnej części stosu MySQL.
Długa odpowiedź:
Zrobiłem kilka badań na ten temat, ponieważ byłem ciekawy, jak radzą sobie z ogromną ilością danych i przeszukują je w szybki sposób. Widziałem ludzi narzekających, że niestandardowe skrypty sieci społecznościowych zwalniają, gdy rośnie liczba użytkowników. Po przeprowadzeniu testów porównawczych z zaledwie 10 tysiącami użytkowników i 2,5 milionami połączeń znajomych - nawet nie próbując zawracać sobie głowy uprawnieniami grupowymi, polubieniami i wpisami na ścianie - szybko okazało się, że to podejście jest wadliwe. Spędziłem więc trochę czasu na przeszukiwaniu sieci i zastanawiałem się, jak to zrobić lepiej, i trafiłem na ten oficjalny artykuł na Facebooku:
I naprawdę polecam do obejrzenia prezentacji pierwszego linku powyżej przed kontynuować czytanie. To prawdopodobnie najlepsze wyjaśnienie, jak działa FB za kulisami, jakie można znaleźć.
Film i artykuł mówią ci o kilku rzeczach:
Rzućmy okiem na to, połączenia znajomych są u góry po lewej:
Cóż, to jest wykres. :) Nie mówi ci, jak zbudować to w SQL, jest na to kilka sposobów, ale ta strona ma wiele różnych podejść. Uwaga: Weź pod uwagę, że relacyjna baza danych jest tym, czym jest: uważa się, że przechowuje znormalizowane dane, a nie strukturę wykresu. Więc nie będzie działać tak dobrze, jak wyspecjalizowana baza danych grafów.
Weź również pod uwagę, że musisz wykonywać bardziej złożone zapytania niż tylko znajomi znajomych, na przykład gdy chcesz odfiltrować wszystkie lokalizacje wokół danej współrzędnej, które lubisz ty i twoi znajomi znajomych. Wykres jest tutaj idealnym rozwiązaniem.
Nie mogę ci powiedzieć, jak go zbudować, aby działał dobrze, ale najwyraźniej wymaga to kilku prób i błędów oraz testów porównawczych.
Oto mój rozczarowujący test tylko dla znalezisk przyjaciół znajomych:
Schemat bazy danych:
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;
Zapytanie o znajomych znajomych:
( 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 )
Naprawdę zalecam utworzenie przykładowych danych z co najmniej 10 tys. Rekordów użytkowników, z których każdy ma co najmniej 250 połączeń znajomych, a następnie uruchomienie tego zapytania. Na moim komputerze (i7 4770k, SSD, 16GB RAM) wynik dla tego zapytania wyniósł ~ 0,18 sekundy . Może da się to zoptymalizować, nie jestem geniuszem DB (sugestie są mile widziane). Jednakże, jeśli ten Wagi liniowe jesteś już w 1,8 sekundy za jedyne 100k użytkowników, 18 sekund do 1 miliona użytkowników.
Może to nadal brzmieć OK dla ~ 100 000 użytkowników, ale weź pod uwagę, że właśnie pobrałeś znajomych znajomych i nie wykonałeś żadnego bardziej złożonego zapytania, takiego jak „ wyświetlaj mi tylko posty od znajomych znajomych + sprawdź uprawnienia, czy mam pozwolenie czy NIE aby zobaczyć niektóre z nich + wykonaj zapytanie podrzędne, aby sprawdzić, czy któryś mi się podobał ". Chcesz pozwolić DB sprawdzać, czy już polubiłeś post, czy nie, albo będziesz musiał to zrobić w kodzie. Weź również pod uwagę, że nie jest to jedyne zapytanie, które uruchamiasz i że masz jednocześnie więcej niż aktywnych użytkowników w mniej lub bardziej popularnej witrynie.
Myślę, że moja odpowiedź odpowiada na pytanie, w jaki sposób Facebook bardzo dobrze zaprojektował relacje z przyjaciółmi, ale przykro mi, że nie mogę powiedzieć, jak to zaimplementować, aby działało szybko. Wdrożenie sieci społecznościowej jest łatwe, ale upewnienie się, że działa dobrze, zdecydowanie nie jest - IMHO.
Zacząłem eksperymentować z OrientDB w celu wykonywania zapytań grafowych i mapowania moich krawędzi do podstawowej bazy danych SQL. Jeśli kiedykolwiek to zrobię, napiszę o tym artykuł.
źródło
Moim najlepszym założeniem jest to, że stworzyli strukturę wykresu . Węzły to użytkownicy, a „przyjaźnie” to krawędzie.
Zachowaj jedną tabelę użytkowników, drugą tabelę krawędzi. Następnie możesz zachować dane o krawędziach, takie jak „dzień, w którym się zaprzyjaźnili”, „stan zatwierdzenia” itp.
źródło
Najprawdopodobniej jest to relacja wiele do wielu:
FriendList (tabela)
EDYTOWAĆ
Tabela użytkowników prawdopodobnie nie ma adresu e-mail user_email jako PK, prawdopodobnie jako unikalnego klucza.
użytkownicy (tabela)
źródło
Zapoznaj się z tymi artykułami opisującymi, jak powstają LinkedIn i Digg:
Jest też „Big Data: Viewpoints from the Facebook Data Team”, które mogą być pomocne:
http://developer.yahoo.net/blogs/theater/archives/2008/01/nextyahoonet_big_data_viewpoints_from_the_fac.html
Jest też ten artykuł, który mówi o nierelacyjnych bazach danych i sposobie ich używania przez niektóre firmy:
http://www.readwriteweb.com/archives/is_the_relational_database_doomed.php
Zobaczysz, że te firmy mają do czynienia z hurtowniami danych, partycjonowanymi bazami danych, buforowaniem danych i innymi koncepcjami wyższego poziomu, z którymi większość z nas nigdy nie ma do czynienia na co dzień. A przynajmniej może nie wiemy, że tak jest.
W pierwszych dwóch artykułach znajduje się wiele linków, które powinny dać ci więcej informacji.
AKTUALIZACJA 20.10.2014
Murat Demirbas napisał podsumowanie
http://muratbuffalo.blogspot.com/2014/10/facebooks-software-architecture.html
HTH
źródło
Nie jest możliwe pobranie danych z RDBMS dla danych znajomych użytkowników w przypadku danych, które przekraczają ponad pół miliarda w stałym czasie, więc Facebook zaimplementował to za pomocą bazy danych hash (bez SQL) i otworzył bazę danych o nazwie Cassandra.
Tak więc każdy użytkownik ma swój własny klucz i szczegóły dotyczące znajomych w kolejce; aby wiedzieć, jak działa Cassandra, spójrz na to:
http://prasath.posterous.com/cassandra-55
źródło
Ten ostatni post z czerwca 2013 r. Zawiera szczegółowe wyjaśnienia dotyczące przejścia od baz danych relacji do obiektów z powiązaniami dla niektórych typów danych.
https://www.facebook.com/notes/facebook-engineering/tao-the-power-of-the-graph/10151525983993920
Istnieje dłuższy artykuł dostępny pod adresem https://www.usenix.org/conference/atc13/tao-facebook's-distributed-data-store-social-graph
źródło
Szukasz kluczy obcych. Zasadniczo nie możesz mieć tablicy w bazie danych, jeśli nie ma własnej tabeli.
Przykładowy schemat:
źródło
Jest to rodzaj graficznej bazy danych: http://components.neo4j.org/neo4j-examples/1.2-SNAPSHOT/social-network.html
Nie jest to związane z relacyjnymi bazami danych.
Google dla graficznych baz danych.
źródło
Pamiętaj, że tabele bazy danych są zaprojektowane tak, aby rosły pionowo (więcej wierszy), a nie poziomo (więcej kolumn)
źródło
Jeśli chodzi o wydajność tabeli wiele-do-wielu, jeśli masz 2 32-bitowe inty łączące identyfikatory użytkowników, podstawowa pamięć dla 200 000 000 użytkowników, średnio 200 znajomych na osobę, wynosi nieco poniżej 300 GB.
Oczywiście będziesz potrzebować partycjonowania i indeksowania, a nie będziesz tego przechowywać w pamięci dla wszystkich użytkowników.
źródło
Prawdopodobnie istnieje tabela, która przechowuje relację użytkownika znajomego <->, powiedzmy „frnd_list”, zawierającą pola „user_id”, „frnd_id”.
Za każdym razem, gdy użytkownik doda innego użytkownika jako znajomego, tworzone są dwa nowe wiersze.
Na przykład załóżmy, że mój identyfikator to „deep9c” i dodaję użytkownika o identyfikatorze „akash3b” jako znajomego, a następnie w tabeli „frnd_list” zostaną utworzone dwa nowe wiersze z wartościami („deep9c”, „akash3b”) i („akash3b ',' deep9c ').
Teraz, pokazując listę znajomych konkretnemu użytkownikowi, prosty sql zrobiłby to: "select frnd_id z frnd_list gdzie user_id =" gdzie jest id zalogowanego użytkownika (przechowywany jako atrybut sesji).
źródło