Lors de la construction d'Ekit, un outil SaaS collaboratif reposant sur des schémas hautement dynamiques, nous avons rencontré un défi MongoDB récurrent qui est courant dans les plateformes axées sur les développeurs.
Lorsque les utilisateurs peuvent définir librement leurs propres champs personnalisés, la création de nouveaux index pour chaque changement de schéma devient rapidement ingérable.
Cet article partage une approche testée en production qui s'est révélée fiable sur un ensemble de données d'environ 15 millions de documents.
Le défi
La difficulté principale réside dans la possibilité de champs définis par l'utilisateur tout en maintenant des performances de requête prévisibles.
Sur de petites collections, les index wildcard peuvent fonctionner raisonnablement bien, mais leur comportement devient beaucoup moins fiable à mesure que le volume de données augmente.
La configuration
Pour maintenir un comportement d'indexation stable et prévisible, nous avons mis en œuvre une approche d'allocation d'index.
Les champs définis par l'utilisateur sont mappés à un petit ensemble fixe de slots indexés.
Pour valider la conception, environ 15 millions de documents ont été injectés dans la collection.
Au départ, nous supposions que les performances dépendraient principalement de la présence des bons index. En pratique, la forme de la requête et la stratégie de pagination se sont révélées tout aussi critiques.
4 slots de chaîne
1 slot entier
1 slot de date
Ce qui a eu le plus d'impact
Recherche par préfixe ancré
En structurant les requêtes autour de recherches par préfixe ancré, certaines recherches sont passées de plusieurs secondes à environ 2 à 3 millisecondes.
L'utilisation de explain() a rendu la raison claire : une fois que l'index était correctement utilisé, le nombre de documents scannés a chuté.
Pagination par clé au lieu de décalages
La pagination basée sur des décalages utilisant skip() et limit() ne se développe pas à ce volume de données.
Passer à une stratégie de pagination basée sur des clés permet à chaque requête de scanner une plage petite et prévisible.
En conséquence, la latence reste stable autour de 2 millisecondes, même lors de la navigation en profondeur dans l'ensemble de données.
Résultat
Une fois ces changements en place, le système s'est stabilisé très rapidement.
Cela n'est pas censé être une solution miracle, mais il était rassurant de voir MongoDB gérer cette charge de travail proprement pendant que nous continuions à travailler sur la couche UX collaborative d'Ekit.
Cet article a été initialement partagé sur r/mongodb et fait partie de mes notes techniques continues lors de la construction d'Ekit.
Discussion
Comment gérez-vous les recherches par préfixe rapides à grande échelle dans MongoDB ?
Avez-vous expérimenté l'allocation d'index par rapport aux index wildcard pour des schémas dynamiques ?