Indexation Mongoose dans le code de production

124

Selon la documentation de Mongoose pour MongooseJSet MongoDB/ Node.js:

Lorsque votre application démarre, Mongoose appelle automatiquement ensureIndexchaque index défini dans votre schéma. Bien qu'il soit utile pour le développement, il est recommandé de désactiver ce comportement en production car la création d'index peut avoir un impact significatif sur les performances. Désactivez le comportement en définissant l' autoIndexoption de votre schéma sur false.

Cela semble indiquer la suppression de l'indexation automatique de la mangouste avant le déploiement afin d'optimiser Mongoose en demandant à Mongo de parcourir tous les index au démarrage de l'application, ce qui semble logique.

Quelle est la bonne façon de gérer l'indexation dans le code de production? Peut-être qu'un script externe devrait générer des index? Ou peut ensureIndex- être est-il inutile si une seule application est le seul lecteur / écrivain d'une collection, car elle continuera un index à chaque fois qu'une écriture de base de données se produit?

Edit: Pour compléter, MongoDB fournit une bonne documentation sur la façon de faire l'indexation, mais pas pourquoi ni quand des directives d'indexation explicites doivent être effectuées. Il me semble que les index devraient être tenus à jour automatiquement par les applications d'écriture sur les collections avec des index existants et c'est ensureIndexvraiment plus une chose ponctuelle (faite lorsqu'un nouvel index est appliqué), auquel cas celui de Mongoose autoIndexdevrait être un no-op sous un redémarrage normal du serveur.

Nick S.
la source

Réponses:

135

Je n'ai jamais compris pourquoi la documentation Mongoose recommande si largement la désactivation autoIndexen production. Une fois l'index ajouté, les ensureIndexappels suivants verront simplement que l'index existe déjà, puis reviendront. Cela n'a donc un effet sur les performances que lorsque vous créez l'index pour la première fois, et à ce moment-là, les collections sont souvent vides, donc la création d'un index serait de toute façon rapide.

Ma suggestion est de laisser autoIndexactivé sauf si vous avez une situation particulière où cela vous pose des problèmes; comme si vous souhaitez ajouter un nouvel index à une collection existante qui contient des millions de documents et que vous souhaitez plus de contrôle sur le moment de sa création.

JohnnyHK
la source
10
J'ai une question à ajouter ... Et si je la mets sur false? Que les index seront créés lorsque j'insère les données ou dois-je les créer explicitement. Je suis désolé si c'est une question novice, mais il serait vraiment utile que vous y répondiez.
Saransh Mohapatra
5
@SaranshMohapatra Lorsque la valeur autoIndexest false, vous devez appeler ensureIndexes sur votre modèle pour créer ses index.
JohnnyHK
Puis-je devoir l'appeler à chaque fois ou juste une fois pour définir le modèle?
Saransh Mohapatra
@SaranshMohapatra lorsque vous définissez (compilez) votre modèle. Je fais cela lorsque je lance l'application pour la première fois. Maintenant, le plus dur est de décider de supprimer tous les index et de les recréer, au cas où vous changeriez de schéma.
Moss
3
@JohnnyHK êtes-vous toujours d'accord avec votre réponse maintenant que nous sommes presque 2016?
Alexander Mills
41

Bien que je sois d'accord avec la réponse acceptée, il convient de noter que, selon le manuel MongoDB , ce n'est pas la méthode recommandée pour ajouter des index sur un serveur de production:

Si votre application inclut des opérations ensureIndex () et qu'un index n'existe pas pour d'autres problèmes opérationnels, la création de l'index peut avoir un impact important sur les performances de la base de données.

Pour éviter les problèmes de performances, assurez-vous que votre application vérifie les index au démarrage à l'aide de la méthode getIndexes () ou de la méthode équivalente pour votre pilote et s'arrête si les index appropriés n'existent pas. Créez toujours des index dans les instances de production à l'aide d'un code d'application distinct, pendant les fenêtres de maintenance désignées.

Bien sûr, cela dépend vraiment de la façon dont votre application est structurée et déployée. Si vous déployez sur Heroku, par exemple, et que vous n'utilisez pas la fonction de pré - démarrage de Heroku , il est probable que votre application ne traite pas du tout les demandes au démarrage, et il est donc probablement sûr de créer un index à ce moment-là.

En plus de cela, à partir de la réponse acceptée:

Cela n'a donc un effet sur les performances que lorsque vous créez l'index pour la première fois, et à ce moment-là, les collections sont souvent vides, donc la création d'un index serait de toute façon rapide.

Si vous avez réussi à faire clouer votre modèle de données et vos requêtes pour la première fois, c'est bien, et souvent le cas. Cependant, si vous ajoutez de nouvelles fonctionnalités à votre application, avec une nouvelle requête DB sur une propriété sans index, vous vous retrouverez souvent à ajouter un index à une collection contenant de nombreux documents existants.

C'est le moment où vous devez être prudent lors de l'ajout d'index et examiner attentivement les implications en termes de performances. Par exemple, vous pouvez créer l'index en arrière-plan :

db.ensureIndex({ name: 1 }, { background: true });
Tom Spencer
la source
3
Ok, donc tout ce que vous avez à faire est de NE PAS démarrer votre serveur tant que tous les rappels ensureIndex n'ont pas été déclenchés pour chaque collection.
Alexander Mills
@AlexMills comment vous assurez-vous cela?
lonelymo
async.each (Object.keys (models), function (key, cb) {models [key] .ensureIndexes (cb)}, cb)
Alexander Mills
appelez simplement ensureIndexes sur chaque modèle de mangouste, attendez que tout se termine, puis démarrez votre serveur; Je recommande également d'attendre que les connexions db se produisent avant de démarrer votre serveur
Alexander Mills
2
Il n'y en a ensureIndexplus. Il y en a createIndexplutôt. Ai-je raison?
jack blank
1

utilisez ce code de bloc pour gérer le mode production:

const autoIndex = process.env.NODE_ENV !== 'production';
mongoose.connect('mongodb://localhost/collection', { autoIndex });
Masih Jahangiri
la source