MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

MongoDB (noSQL) kiedy dzielić kolekcje

Jak już napisano, nie ma reguł takich jak druga normalna forma SQL.

Istnieje jednak kilka najlepszych praktyk i typowych pułapek związanych z optymalizacją dla MongoDB, które wymienię tutaj.

Nadużywanie osadzania

Limit BSON

Wbrew powszechnemu przekonaniu nie ma nic złego w referencjach. Załóżmy, że masz bibliotekę książek i chcesz śledzić wypożyczenia. Możesz zacząć od takiego modelu

{
  // We use ISBN for its uniqueness 
  _id: "9783453031456"
  title: "Schismatrix",
  author: "Bruce Sterling",
  rentals: [
    {
      name:"Markus Mahlberg,
      start:"2015-05-05T03:22:00Z",
      due:"2015-05-12T12:00:00Z"
    }
  ]
}

Chociaż z tym modelem jest kilka problemów, najważniejszy nie jest oczywisty – będzie ograniczona liczba wypożyczeń ze względu na fakt, że dokumenty BSON mają limit rozmiaru 16 MB.

Problem z migracją dokumentów

Innym problemem związanym z przechowywaniem wypożyczeń w macierzy byłoby to, że powodowałoby to stosunkowo częste migracje dokumentów, co jest dość kosztowną operacją. Dokumenty BSON nigdy nie są partycjonowane i tworzone z dodatkową przestrzenią przydzieloną z góry, używaną, gdy rosną. Ta dodatkowa przestrzeń nazywa się dopełnieniem. Po przekroczeniu dopełnienia dokument jest przenoszony do innej lokalizacji w plikach danych i przydzielana jest nowa przestrzeń dopełniania. Tak częste dodawanie danych powoduje częste migracje dokumentów. Dlatego najlepszą praktyką jest zapobieganie częstym aktualizacjom zwiększającym rozmiar dokumentu i używanie zamiast tego odnośników.

Na przykład zmienimy nasz pojedynczy model i stworzymy drugi. Po pierwsze, wzór książki

{
  _id: "9783453031456",
  title:"Schismatrix",
  author: "Bruce Sterling"
}

Drugi model do wypożyczenia wyglądałby tak

{
  _id: new ObjectId(),
  book: "9783453031456",
  rentee: "Markus Mahlberg",
  start: ISODate("2015-05-05T03:22:00Z"),
  due: ISODate("2015-05-05T12:00:00Z"),
  returned: ISODate("2015-05-05T11:59:59.999Z")
}

To samo podejście można oczywiście zastosować w przypadku autora lub najemcy.

Problem z nadmierną normalizacją

Cofnijmy się jakiś czas wstecz. Deweloper identyfikuje podmioty zaangażowane w sprawę biznesową, definiuje ich właściwości i relacje, pisze odpowiednie klasy podmiotów, uderza głową w ścianę przez kilka godzin, aby uzyskać wymagane działanie potrójnego JOIN dla przypadku użycia i wszyscy żyli długo i szczęśliwie. Dlaczego więc używać NoSQL w ogóle, a MongoDB w szczególności? Ponieważ nikt nie żył długo i szczęśliwie. Takie podejście skaluje się okropnie i prawie wyłącznie jedynym sposobem skalowania jest pion.

Ale główna różnica w NoSQL polega na tym, że modelujesz swoje dane zgodnie z pytaniami, na które potrzebujesz odpowiedzi.

Biorąc to pod uwagę, spójrzmy na typową relację n:m i weźmy jako przykład relację od autorów do książek. W SQL masz 3 tabele:dwie dla Twoich encji (książki i autorzy ) i jeden dla relacji (Kto jest autorem której książki? ). Oczywiście możesz wziąć te stoły i stworzyć ich kolekcje. Ale ponieważ w MongoDB nie ma JOIN, potrzebujesz trzech zapytań (jedno dla pierwszej encji, jedno dla jej relacji i jedno dla encji pokrewnych), aby znaleźć powiązane dokumenty encji. Nie miałoby to sensu, ponieważ podejście trzech tabel dla relacji n:m zostało specjalnie wymyślone, aby przezwyciężyć ścisłe schematy, które wymuszają bazy danych SQL. Ponieważ MongoDB ma elastyczny schemat, pierwsze pytanie brzmi:gdzie przechowywać relację, zachowując problemy wynikające z nadużywania osadzania w umyśle. Ponieważ w nadchodzących latach autor może napisać sporo książek, ale autorstwo książki rzadko, jeśli w ogóle się zmienia, odpowiedź jest prosta:przechowujemy autorów jako odniesienie do autorów w danych książek

{
  _id: "9783453526723",
  title: "The Difference Engine",
  authors: ["idOfBruceSterling","idOfWilliamGibson"]
}

A teraz możemy znaleźć autorów tej książki, wykonując dwa zapytania:

var book = db.books.findOne({title:"The Difference Engine"})
var authors = db.authors.find({_id: {$in: book.authors})

Mam nadzieję, że powyższe pomoże Ci zdecydować, kiedy faktycznie „podzielić” swoje kolekcje i ominąć najczęstsze pułapki.

Wniosek

Jeśli chodzi o Twoje pytania, oto moje odpowiedzi

  1. Jak napisano wcześniej:Nie , ale pamiętanie o ograniczeniach technicznych powinno dać wyobrażenie, kiedy może to mieć sens.
  2. To nie jest złe — o ile pasuje do Twoich przypadków użycia . Jeśli masz daną kategorię i jej _id , łatwo jest znaleźć powiązane produkty. Podczas ładowania produktu możesz łatwo uzyskać kategorie, do których należy, nawet wydajnie, ponieważ _id jest indeksowany domyślnie.
  3. Muszę jeszcze znaleźć przypadek użycia, którego nie można zrobić z MongoDB, chociaż niektóre rzeczy mogą być nieco bardziej skomplikowane w MongoDB. To, co powinieneś zrobić, to zebrać sumę wymagań funkcjonalnych i niefunkcjonalnych i sprawdzić, czy zalety przeważają nad wadami. Moja praktyczna zasada:jeśli na liście wymagań znajduje się jedno z „skalowalności” lub „wysokiej dostępności/automatycznego przełączania awaryjnego”, MongoDB jest wart więcej niż tylko spojrzenie.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Konfigurowanie zestawu replik MongoDB

  2. MongoDB zmienia nazwę pola bazy danych w tablicy

  3. CRUD nodejs/express server:app.put req.body jest pusty

  4. mongodump Failed:zła opcja:można zrzucić tylko jedną kolekcję na standardowe wyjście

  5. Parser BASH BSON