MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB (noSQL) quand diviser les collections

Comme déjà écrit, il n'y a pas de règles comme la deuxième forme normale pour SQL.

Cependant, il existe quelques bonnes pratiques et des pièges courants liés à l'optimisation pour MongoDB que je vais énumérer ici.

Utilisation excessive de l'intégration

La limite BSON

Contrairement à la croyance populaire, il n'y a rien de mal avec les références. Supposons que vous ayez une bibliothèque de livres et que vous souhaitiez suivre les locations. Vous pourriez commencer avec un modèle comme celui-ci

{
  // 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"
    }
  ]
}

Bien qu'il y ait plusieurs problèmes avec ce modèle, le plus important n'est pas évident - il y aura un nombre limité de locations en raison du fait que les documents BSON ont une limite de taille de 16 Mo.

Le problème de migration de documents

L'autre problème avec le stockage des locations dans un tableau serait que cela entraînerait des migrations de documents relativement fréquentes, ce qui est une opération assez coûteuse. Les documents BSON ne sont jamais partitionnés et créés avec un espace supplémentaire alloué à l'avance utilisé lorsqu'ils grandissent. Cet espace supplémentaire est appelé rembourrage. Lorsque le remplissage est dépassé, le document est déplacé vers un autre emplacement dans les fichiers de données et un nouvel espace de remplissage est alloué. Ainsi, les ajouts fréquents de données entraînent des migrations fréquentes de documents. Par conséquent, il est préférable d'empêcher les mises à jour fréquentes d'augmenter la taille du document et d'utiliser des références à la place.

Donc, pour l'exemple, nous changerions notre modèle unique et en créerions un deuxième. Tout d'abord, le modèle du livre

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

Le deuxième modèle pour la location ressemblerait à ceci

{
  _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")
}

La même approche pourrait bien sûr être utilisée pour l'auteur ou le locataire.

Le problème de la sur-normalisation

Revenons un peu en arrière. Un développeur identifierait les entités impliquées dans une analyse de rentabilisation, définirait leurs propriétés et leurs relations, écrirait les classes d'entités correspondantes, se cognerait la tête contre le mur pendant quelques heures pour obtenir le triple travail JOIN intérieur-extérieur-au-dessus-et-au-delà requis pour le cas d'utilisation et tous vécurent heureux pour toujours. Alors pourquoi utiliser NoSQL en général et MongoDB en particulier ? Parce que personne n'a vécu heureux pour toujours. Cette approche évolue horriblement et presque exclusivement la seule façon d'évoluer est verticale.

Mais la principale différence avec NoSQL est que vous modélisez vos données en fonction des questions auxquelles vous devez obtenir des réponses.

Cela étant dit, examinons une relation n:m typique et prenons la relation des auteurs aux livres comme exemple. En SQL, vous auriez 3 tables :deux pour vos entités (livres et auteurs ) et un pour la relation (Qui est l'auteur de quel livre ? ). Bien sûr, vous pouvez prendre ces tables et créer leurs collections équivalentes. Mais, comme il n'y a pas de JOIN dans MongoDB, vous auriez besoin de trois requêtes (une pour la première entité, une pour ses relations et une pour les entités associées) pour trouver les documents associés d'une entité. Cela n'aurait aucun sens, puisque l'approche à trois tables pour les relations n:m a été spécifiquement inventée pour surmonter les schémas stricts appliqués par les bases de données SQL. Puisque MongoDB a un schéma flexible, la première question serait de savoir où stocker la relation, en gardant les problèmes résultant de la surutilisation de l'intégration à l'esprit. Étant donné qu'un auteur peut écrire pas mal de livres dans les années à venir, mais que la paternité d'un livre change rarement, voire pas du tout, la réponse est simple :nous stockons les auteurs en tant que référence aux auteurs dans les données des livres

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

Et maintenant, nous pouvons trouver les auteurs de ce livre en faisant deux requêtes :

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

J'espère que ce qui précède vous aidera à décider quand "diviser" vos collections et à contourner les pièges les plus courants.

Conclusion

Quant à vos questions, voici mes réponses

  1. Comme écrit précédemment :Non , mais garder à l'esprit les limitations techniques devrait vous donner une idée du moment où cela pourrait avoir un sens.
  2. Ce n'est pas mal, tant qu'il correspond à votre ou vos cas d'utilisation . Si vous avez une catégorie donnée et son _id , il est facile de trouver les produits associés. Lors du chargement du produit, vous pouvez facilement obtenir les catégories auxquelles il appartient, même efficacement, comme _id est indexé par défaut.
  3. Je n'ai pas encore trouvé de cas d'utilisation qui ne peut pas être fait avec MongoDB, bien que certaines choses puissent devenir un peu plus compliquées avec MongoDB. Ce que vous devriez faire à mon humble avis, c'est de prendre la somme de vos exigences fonctionnelles et non fonctionnelles et de vérifier si les avantages l'emportent sur les inconvénients. Ma règle d'or :si l'une des options "évolutivité" ou "haute disponibilité/basculement automatique" figure sur votre liste d'exigences, MongoDB vaut plus qu'un coup d'œil.