2012-11-30 14 views
10

Biorąc pod uwagę poniższe konkurencyjne schematy z maksymalnie 100 000 znajomych, jestem zainteresowany znalezieniem najbardziej wydajnego dla moich potrzeb.MongoDB embedded vs array sub document performance

doc1 (Indeks na user_id)

{ 
"_id" : "…", 
"user_id" : "1", 
friends : { 
    "2" : { 
     "id" : "2", 
     "mutuals" : 3 
    } 
    "3" : { 
     "id" : "3", 
     "mutuals": "1" 
    } 
    "4" : { 
     "id" : "4", 
     "mutuals": "5" 
    } 
} 
} 

zmienna doc2 (Związek klucz Indeks Multi na user_id & friends.id)

{ 
"_id" : "…", 
"user_id" : "1", 
friends : [ 
    { 
     "id" : "2", 
     "mutuals" : 3 
    }, 
    { 
     "id" : "3", 
     "mutuals": "1" 
    }, 
    { 
     "id" : "4", 
     "mutuals": "5" 
    } 
]} 

nie mogę wydawać się znaleźć żadnych informacji na temat efektywność pobierania pól podrzędnych. Wiem, że Mongo implementuje dane wewnętrznie jako BSON, więc zastanawiam się, czy to oznacza, że ​​wyszukiwanie rzutu jest binarnym O (log n)?

W szczególności, biorąc pod uwagę identyfikator użytkownika, aby ustalić, czy istnieje znajomy z friend_id, w jaki sposób porównają się dwa różne zapytania w każdym schemacie? (Zakładając powyższe indeksy) Zwróć uwagę, że tak naprawdę nie ma znaczenia, co zostało zwrócone, ale zwracana jest wartość null, jeśli istnieje przyjaciel.

Doc1col.find({user_id : "…"}, {"friends.friend_id"}) 
Doc2col.find({user_id : "…", "friends.id" : "friend_id"}, {"_id":1}) 

Interesujący jest także sposób działania modyfikatora $ set. W przypadku schematu 1, biorąc pod uwagę zapytanie Doc1col.update({user_id : "…"}, {"$set" : {"friends.friend_id.mutuals" : 5}), w jaki sposób działa odnośnik na stronie friend.friend_id? Czy jest to operacja O (log n) (gdzie n jest liczbą znajomych)?

Dla schematu 2, w jaki sposób zapytanie Doc2col.update({user_id : "…", "friends.id" : "friend_id"}, {"$set": {"friends.$.mutuals" : 5}) będzie porównywane z powyższym?

+3

Przejdź do stylu tablicy (Doc2), ponieważ klucze dynamiczne prawie nigdy nie są właściwym rozwiązaniem. Nie używaj również cytatów inteligentnych (nie jest to legalna składnia i trudno ją odczytać). – JohnnyHK

+1

Przypuszczam, że Doc2 zużyje się jak kilka bajtów dodatkowego miejsca, ale jak @JohnnyHK mówi, że Doc1 nie jest zbyt dobrym podejściem, zaufaj mi ilości pytań od osób, które używają Doc1, a następnie zdają sobie sprawę, że muszą przejść do Doc2, aby cokolwiek zrobić ze swoim schematem ... – Sammaye

+0

Dzięki za poradę. @Sammaye, dlaczego Doc2 zużyje kilka bajtów dodatkowego miejsca? Czy odnosisz się do indeksu? Btw inteligentne cytaty były błędem z pasty do kopiowania –

Odpowiedz

1

doc1 jest preferowany, jeśli podstawowym wymaganiem jest prezentacja danych do interfejsu użytkownika w ładnym, łatwym do zarządzania pakiecie. Jego proste filtrowanie tylko żądane dane za pomocą projekcji {}, {friends.2 : 1}

zmienna doc2 jest najsilniejszy mecz ponieważ Twój przypadek użycia nie dba o wyniku pamiętać, że nie ma znaczenia, co wrócili i indeksowanie przyspieszy pobrania .

na szczycie tej zmienna doc2 umożliwia znacznie czystszą składnią

db.doc2.findOne({user_id: 1, friends.id : 2}) 

Versus

db.doc1.findOne({ $and : [{ user_id: 1 }, { "friends.2" : {$exists: true} }] }) 

na końcowej nocie, jednak można stworzyć sparse index na doc1 (i korzystać z $ istnieje), ale Twoja możliwość 100 000 przyjaciół - każdy przyjaciel potrzebuje rzadkiego indeksu - czyni to absurdem. w przeciwieństwie do rozsądnej liczby zgłoszeń, powiedzmy, że płeć demograficzna [mężczyzna, kobieta], grupy (0-10,11-16,25-30, ..) lub więcej rzeczy [gin, whisky, wódka, ...]