Comment MongoDB trie-t-il les enregistrements lorsqu'aucun ordre de tri n'est spécifié?

103

Lorsque nous exécutons une requête Mongo find () sans aucun ordre de tri spécifié, qu'est-ce que la base de données utilise en interne pour trier les résultats?

Selon la documentation sur le site Web de mongo :

Lors de l'exécution d'un find () sans paramètres, la base de données renvoie les objets dans l'ordre naturel avant.

Pour les tables standard, l'ordre naturel n'est pas particulièrement utile car, bien que l'ordre soit souvent proche de l'ordre d'insertion, il n'est pas garanti. Cependant, pour les collections limitées, l'ordre naturel est garanti comme étant l'ordre d'insertion. Cela peut être très utile.

Cependant pour les collections standard (collections non plafonnées), quel champ est utilisé pour trier les résultats? Est-ce le champ _id ou autre chose?

Éditer:

Fondamentalement, je suppose que ce que j'essaie d'arriver, c'est que si j'exécute la requête de recherche suivante:

db.collection.find({"x":y}).skip(10000).limit(1000);

À deux moments différents: t1 et t2 , vais-je obtenir des ensembles de résultats différents:

  1. Quand il n'y a pas eu d'écritures supplémentaires entre t1 et t2?
  2. Quand il y a eu de nouvelles écritures entre t1 et t2?
  3. Il y a de nouveaux index qui ont été ajoutés entre t1 et t2?

J'ai effectué des tests sur une base de données temporaire et les résultats que j'ai obtenus sont les mêmes ( Oui ) pour les 3 cas - mais je voulais être sûr et je suis certain que mes cas de test n'étaient pas très complets.

saurabhj
la source

Réponses:

121

Quel est l'ordre de tri par défaut si aucun n'est spécifié?

L'ordre de tri interne par défaut (ou ordre naturel ) est un détail d'implémentation non défini . Le maintien de l'ordre est une surcharge supplémentaire pour les moteurs de stockage et l'API de MongoDB n'impose pas de prévisibilité en dehors d'un cas explicite sort()ou particulier de collections plafonnées de taille fixe auxquelles sont associées des restrictions d'utilisation . Pour les charges de travail typiques, il est souhaitable que le moteur de stockage tente de réutiliser l'espace préalloué disponible et prenne des décisions sur la manière de stocker le plus efficacement les données sur disque et en mémoire.

Sans aucun critère de requête, les résultats seront renvoyés par le moteur de stockage dans l'ordre naturel (c'est-à-dire dans l'ordre dans lequel ils sont trouvés ). L'ordre des résultats peut coïncider avec l'ordre d'insertion, mais ce comportement n'est pas garanti et ne peut pas être invoqué (à l'exception des collections plafonnées).

Quelques exemples qui peuvent affecter l'ordre de stockage (naturel):

  • WiredTiger utilise une représentation différente des documents sur disque par rapport au cache en mémoire, de sorte que l'ordre naturel peut changer en fonction des structures de données internes.
  • Le moteur de stockage MMAPv1 d'origine (supprimé dans MongoDB 4.2) alloue un espace d'enregistrement pour les documents en fonction des règles de remplissage. Si un document dépasse l'espace d'enregistrement actuellement alloué, l'emplacement du document (et l'ordre naturel) sera affecté. De nouveaux documents peuvent également être insérés dans le stockage marqué comme disponible pour une réutilisation en raison de documents supprimés ou déplacés.
  • La réplication utilise un format oplog idempotent pour appliquer les opérations d'écriture de manière cohérente entre les membres du jeu de réplicas. Chaque membre du jeu de réplicas gère des fichiers de données locaux qui peuvent varier dans un ordre naturel, mais qui auront le même résultat de données lorsque les mises à jour oplog sont appliquées.

Et si un index est utilisé?

Si un index est utilisé, les documents seront renvoyés dans l'ordre dans lequel ils ont été trouvés (qui correspond nécessairement à l'ordre d'insertion ou à l'ordre d'E / S). Si plus d'un index est utilisé, l'ordre dépend en interne de l'index qui a identifié le document en premier lors du processus de déduplication.

Si vous voulez un ordre de tri prévisible, vous devez inclure un explicite sort()avec votre requête et avoir des valeurs uniques pour votre clé de tri.

Comment les collections plafonnées maintiennent-elles l'ordre d'insertion?

L'exception d'implémentation notée pour l'ordre naturel dans les collections plafonnées est appliquée par leurs restrictions d'utilisation spéciales: les documents sont stockés dans l'ordre d'insertion mais la taille du document existant ne peut pas être augmentée et les documents ne peuvent pas être supprimés explicitement. La commande fait partie de la conception de la collection plafonnée qui garantit que les documents les plus anciens «vieillissent» en premier.

Stennie
la source
4
Cela signifie-t-il que si j'exécute la même commande find: db.collection.find ({"x": y}). Skip (20000) .limit (1000) à deux moments différents, j'obtiendrai un résultat différent ensembles? Que se passe-t-il s'il n'y a pas eu d'écriture entre les deux commandes?
saurabhj
6
@saurabhj: Ajout de quelques exemples qui affecteront l'ordre naturel. Si des documents ont été déplacés / supprimés, vous pouvez obtenir des ensembles de résultats différents. S'il n'y a pas eu d'insertion / mise à jour / suppression de document, vous devriez obtenir le même résultat. L'ajout d'index n'affecte pas l'emplacement des documents sur le disque.
Stennie
7
Il convient également d'ajouter l'avertissement que si vous utilisez la réplication, l'ordre naturel peut varier entre les membres du jeu de réplicas.
Stennie
Est-ce que quelqu'un sait comment forcer l'un des 2 points commentés ici? Nous avons essayé de modifier des documents mais ils sont toujours retournés dans leur ordre d'insertion ... Je suis curieux de savoir si l'ordre naturel peut être différent de l'ordre d'insertion.
Ferran Maylinch
L'application d'un ordre par défaut (par exemple {createdAt: -1}) est nécessaire pour implémenter des modèles d'interface optimiste (mise à jour des listes de données dans le cache sans attendre la réponse du serveur après une création / mise à jour / suppression). Sinon, vous ne pouvez pas faire correspondre l'ordre optimiste côté client et l'ordre de réponse du serveur.
Eric Burel le
8

Il est retourné dans l'ordre stocké (ordre dans le fichier), mais il n'est pas garanti qu'ils soient dans l'ordre inséré. Ils ne sont pas triés par le champ _id. Parfois, il peut sembler être trié par ordre d'insertion, mais cela peut changer dans une autre demande. Ce n'est pas fiable.

Parvin Gasimzade
la source