web-dev-qa-db-fra.com

Dois-je implémenter l'incrémentation automatique dans MongoDB?

Je passe à MongoDB depuis MySQL. Une architecture familière pour une table users très basique aurait une incrémentation automatique de uid. Voir la propre documentation de Mongo pour ce cas d'utilisation .

Je me demande si c'est la meilleure décision architecturale. D'un point de vue UX, j'aime avoir des UID comme références externes, par exemple dans des URL plus courtes: http://example.com/users/12345

Y a-t-il une troisième voie? Quelqu'un dans IRC Freenode's #mongodb a suggéré de créer une plage d'ID et de les mettre en cache. Je ne sais pas comment mettre en œuvre cela, ni s'il y a une autre voie que je peux emprunter. Je n'ai même pas nécessairement besoin du _id lui-même pour être incrémenté de cette façon. Tant que les users ont tous un uid numérique unique dans le document, je serais heureux.

42
Josh Smith

Josh, aucun identifiant d'incrémentation automatique dans MongoDB et il y a de bonnes raisons. Je dirais aller avec ObjectIds qui sont uniques dans le cluster.

Vous pouvez ajouter l'incrémentation automatique par une collection de séquences et en utilisant findAndModify pour obtenir l'ID suivant à utiliser. Cela ajoutera certainement de la complexité à votre application et peut également affecter la capacité de partitionner votre base de données.

Tant que vous pouvez garantir que vos identifiants générés seront uniques, tout ira bien. Mais le mal de tête sera là.

Vous pouvez consulter ce post pour plus d'informations sur cette question dans le groupe google dédié à MongoDB:

http://groups.google.com/group/mongodb-user/browse_thread/thread/f57b712b2aae6f0b/b4315285e689b9a7?lnk=gst&q=projapati#b4315285e689b9a7

J'espère que cela t'aides.

Merci

18
kheya

Je suis fortement en désaccord avec l'auteur de la réponse sélectionnée qui Aucun identifiant d'incrémentation automatique dans MongoDB et il y a de bonnes raisons. Nous ne connaissons pas les raisons pour lesquelles 10gen n'a pas encouragé l'utilisation d'ID auto-incrémentés. C'est de la spéculation. Je pense que 10gen a fait ce choix car il est tout simplement plus facile de garantir l'unicité des identifiants 12 octets dans un environnement en cluster. Sa solution par défaut qui convient à la plupart des nouveaux arrivants augmente donc l'adoption du produit, ce qui est bon pour les activités de 10gen.

Maintenant, permettez-moi de parler à tout le monde de mon expérience avec ObjectIds dans un environnement commercial.

Je construis un réseau social. Nous avons environ 6 millions d'utilisateurs et chaque utilisateur a environ 20 amis.

Imaginez maintenant que nous ayons une collection qui stocke la relation entre les utilisateurs (qui suit qui). Ça ressemble à ça

_id : ObjectId
user_id : ObjectId
followee_id : ObjectId

sur laquelle nous avons un indice composite unique {user_id, followee_id}. Nous pouvons estimer la taille de cet indice à 12 * 2 * 6M * 20 = 2 Go. Maintenant, c'est l'indice de recherche rapide des personnes que je suis. Pour une recherche rapide des personnes qui me suivent, j'ai besoin d'un index inversé. C'est un autre 2 Go.

Et ce n'est que le début. Je dois porter ces identifiants partout. Nous avons un cluster d'activités où nous stockons votre flux d'actualités. C'est chaque événement que vous ou vos amis faites. Imaginez combien d'espace cela prend.

Et finalement, l'un de nos ingénieurs a pris une décision inconsciente et a décidé de stocker les références sous forme de chaînes qui représentent ObjectId qui double sa taille.

Que se passe-t-il si un index ne tient pas dans la RAM? Rien de bon, dit 10gen:

Lorsqu'un index est trop volumineux pour tenir dans la RAM, MongoDB doit lire l'index à partir du disque, ce qui est une opération beaucoup plus lente que la lecture à partir de la RAM. Gardez à l'esprit qu'un index s'inscrit dans RAM lorsque votre serveur a RAM disponible pour l'index combiné avec le reste de l'ensemble de travail.

Cela signifie que les lectures sont lentes. La contention de verrouillage augmente. L'écriture ralentit également. Voir une contention de verrouillage en 80% -nish n'est plus un choc pour moi.

Avant de vous en rendre compte, vous vous êtes retrouvé avec un cluster de 460 Go que vous devez diviser en fragments et qui est assez difficile à manipuler.

Facebook utilise 64 bits tant que l'ID utilisateur :) Il y a une raison à cela. Vous pouvez générer des ID séquentiels

  • en utilisant les conseils de 10gen .
  • utiliser mysql comme stockage de compteurs (si vous êtes préoccupé par la vitesse, jetez un œil à handlersocket )
  • en utilisant le service de génération d'ID que vous avez créé ou en utilisant quelque chose comme Snowflake par Twitter.

Voici donc mes conseils généraux à tout le monde. Veuillez rendre vos données aussi petites que possible. Lorsque vous grandissez, cela vous fera économiser beaucoup de nuits blanches.

84
expert

Il y a donc un problème fondamental avec les ID "auto-incrémentés". Lorsque vous avez 10 serveurs différents (fragments dans MongoDB), qui choisit l'ID suivant?

Si vous voulez un seul ensemble d'ID à incrémentation automatique, vous devez avoir une seule autorité pour choisir ces ID. Dans MySQL, c'est généralement assez facile car vous n'avez qu'un seul serveur qui accepte les écritures. Mais les grands déploiements de MongoDB exécutent un partitionnement qui n'a pas cette "autorité centrale".

MongoDB utilise ObjectIds sur 12 octets pour que chaque serveur puisse créer de nouveaux documents de manière unique sans dépendre d'une seule autorité.

Voici donc la grande question: "pouvez-vous vous permettre d'avoir une seule autorité"?

Si c'est le cas, vous pouvez utiliser findAndModify pour garder une trace du "dernier ID le plus élevé", puis vous pouvez insérer avec cela.

C'est le processus décrit dans votre lien. La faiblesse évidente ici est que vous devez techniquement faire deux écritures pour chaque insert. Cela peut ne pas évoluer très bien, vous voulez probablement l'éviter sur les données avec un taux d'insertion élevé. Cela peut fonctionner pour les utilisateurs, il ne fonctionnera probablement pas pour le suivi des clics.

16
Gates VP

Il n'y a rien de tel qu'une incrémentation automatique dans MongoDB mais vous pouvez stocker vos propres compteurs dans une collection dédiée et $ inc la valeur associée du compteur selon les besoins. Puisque $ inc est une opération atomique, vous ne verrez pas de doublons.

10
Andreas Jung

Le Mongo ObjectId par défaut - celui utilisé dans le champ _id - est incrémenté.

Mongo utilise un horodatage (secondes depuis l'époque Unix) comme première portion de 4 octets de sa composition 4-3-2-3, très similaire (sinon exactement) à la même composition qu'un UUID version 1. Et cet ObjectId est généré au moment de l'insertion (si aucun autre type de _id n'est fourni par l'utilisateur/client)

Ainsi, l'ObjectId est de nature ordinale; en outre, le tri par défaut est basé sur cet horodatage incrémentiel.

On pourrait le considérer comme une version mise à jour des identifiants à incrémentation automatique (index ++) utilisés dans de nombreux dbms.

3
Gabe Rainbow