web-dev-qa-db-fra.com

MongoDB et clés primaires composites

J'essaie de déterminer la meilleure façon de traiter une clé primaire composite dans une base de données Mongo. La clé principale pour interagir avec les données de ce système est constituée de 2 uuides. La combinaison d'uuids est garantie d'être unique, mais aucun des uuids individuels ne l'est.

Je vois deux façons de gérer cela:

  1. Utilisez un objet pour la clé primaire qui est composé de 2 valeurs (comme suggéré ici )

  2. Utilisez un identifiant d'objet mongo généré automatiquement comme clé primaire, stockez ma clé dans deux champs distincts, puis créez un index composite sur ces deux champs

  3. Faire de la clé primaire un hachage des 2 uuids

  4. Une autre solution géniale que je ne connais pas actuellement

Quelles sont les implications de performance de ces approches?

Pour l'option 1, je m'inquiète des performances d'insertion en raison de la présence de clés non séquentielles. Je sais que cela peut tuer les systèmes RDBMS traditionnels et j'ai vu des indications que cela pourrait être vrai également dans MongoDB.

Pour l'option 2, il semble un peu étrange d'avoir une clé primaire qui ne serait jamais utilisée par le système. En outre, il semble que les performances des requêtes ne soient pas aussi bonnes que dans l'option 1. Dans un SGBDR traditionnel, un index cluster donne les meilleurs résultats de requête. Quelle est la pertinence de ceci dans MongoDB?

Pour l'option 3, cela créerait un seul champ id, mais encore une fois, il ne serait pas séquentiel lors de l'insertion. Y a-t-il d'autres avantages/inconvénients à cette approche?

Pour l'option 4, eh bien ... qu'est-ce que l'option 4?

En outre, il y a une discussion sur l'utilisation possible de CouchDB au lieu de MongoDB à un moment donné dans le futur. L'utilisation de CouchDB suggérerait-elle une solution différente?

PLUS D'INFO: quelques informations sur le problème peuvent être trouvées ici

45
herbrandson

Vous devriez choisir l'option 1.

La raison principale est que vous dites que vous êtes préoccupé par les performances - l'utilisation de l'index _id qui est toujours là et déjà unique vous permettra d'économiser d'avoir à maintenir un deuxième index unique.

Pour l'option 1, je m'inquiète des performances de l'insertion pour avoir des clés non séquentielles. Je sais que cela peut tuer les systèmes RDBMS traditionnels et j'ai vu des indications que cela pourrait être vrai également dans MongoDB.

Vos autres options n'évitent pas ce problème, elles le déplacent simplement de l'index _id vers l'index unique secondaire - mais maintenant vous avez deux index, une qui est équilibrée à droite et l'autre qui est à accès aléatoire.

Il n'y a qu'une seule raison de remettre en question l'option 1 et c'est si vous prévoyez d'accéder aux documents par une seule ou simplement l'autre valeur UUID. Tant que vous fournissez toujours les deux valeurs et (cette partie est très importante) que vous les commandez toujours de la même manière dans toutes vos requêtes, alors l'index _id remplira efficacement son rôle.

Pour expliquer pourquoi vous devez vous assurer de toujours commander les deux valeurs UUID de la même manière, lorsque vous comparez des sous-documents { a:1, b:2 } n'est pas égal à { b:2, a:1 } - vous pourriez avoir une collection où deux documents avaient ces valeurs pour _id. Donc, si vous stockez _id avec le champ a en premier, vous devez toujours conserver cet ordre dans tous vos documents et requêtes.

L'autre prudence est que l'indice sur _id:1 sera utilisable pour la requête:

db.collection.find({_id:{a:1,b:2}}) 

mais il sera pas utilisable pour la requête

db.collection.find({"_id.a":1, "_id.b":2})
39
Asya Kamsky

J'ai une option 4 pour vous:

Utilisez le champ automatique _id Et ajoutez 2 index de champ unique pour les deux uuid au lieu d'un seul index composite.

  1. L'index _id Serait séquentiel (bien que ce soit moins important dans MongoDB), facilement partageable, et vous pouvez laisser MongoDB le gérer.
  2. Les 2 index uuid vous permettent de faire tout type de requête dont vous avez besoin (avec le premier, avec le second ou avec les deux dans n'importe quel ordre) et ils occupent moins d'espace qu'un index composé.
  3. Dans le cas où vous utilisez les deux index (et d'autres également) dans la même requête, MongoDBles entrecroise (nouveau dans la v2.6) comme si vous utilisiez un index composé.
6
i3arnon

J'irais pour l'option 2 et il y a pourquoi

  1. Le fait d'avoir deux champs distincts au lieu de celui concaténé des deux uuids comme suggéré dans 1st, vous laissera la flexibilité de créer d'autres combinaisons d'index pour prendre en charge les futures requêtes de requête ou s'il s'avère que la cardinalité d'une clé est supérieure à l'autre.
  2. avoir des clés non séquentielles pourrait vous aider à éviter les points chauds lors de l'insertion dans un environnement fragmenté, donc ce n'est pas une si mauvaise option. Le sharding est le meilleur moyen, à mon avis, de mettre à l'échelle les insertions et les mises à jour sur les collections, car le verrouillage en écriture est au niveau de la base de données (avant 2.6) ou au niveau de la collection (version 2.6)
4
Boris

J'aurais choisi l'option 2. Vous pouvez toujours créer un index qui gère les deux champs UUID, et les performances devraient être les mêmes qu'une clé primaire composée, sauf que ce sera beaucoup plus facile à utiliser.

De plus, d'après mon expérience, je n'ai jamais regretté de donner à quelque chose un identifiant unique, même s'il n'était pas strictement requis. C'est peut-être une opinion impopulaire.

2
Brent