View a markdown version of this page

Planificateur de requêtes v2 - Amazon DocumentDB

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Planificateur de requêtes v2

Le nouveau planificateur de requêtes pour Amazon DocumentDB (version 2.0 du planificateur) propose des fonctionnalités avancées d'optimisation des requêtes et des performances améliorées. La version 2.0 de Planner pour Amazon DocumentDB 5.0 offre des performances jusqu'à 10 fois supérieures à celles de la version précédente lors de l'utilisation d'updateopérateurs find et d'index. Les améliorations de performances proviennent principalement de l'utilisation de plans d'indexation plus optimaux et de la prise en charge de l'analyse d'index pour les opérateurs tels que les opérateurs de négation ($neq,$nin) et les opérateurs imbriqués$elementMatch. Les requêtes Planner version 2.0 s'exécutent plus rapidement grâce à de meilleures techniques d'estimation des coûts, à des algorithmes optimisés et à une stabilité accrue. La version 2.0 de Planner prend également en charge les API de filtrage du cache des plans, ce qui améliore la stabilité du planificateur. Grâce à cette fonctionnalité, Amazon DocumentDB 5.0 offre désormais la possibilité de choisir parmi les différentes versions du planificateur de requêtes.

Conditions préalables

Les prérequis suivants s'appliquent à la version 2.0 du planificateur :

  • La version 2.0 de Planner est disponible dans tous les Régions AWS pays où la version 5.0 du moteur est disponible.

  • Pour choisir d'utiliser la version 2.0 comme planificateur de requêtes par défaut, votre cluster doit utiliser le correctif moteur 3.0.15902 ou une version ultérieure d'Amazon DocumentDB version 5.0. Pour savoir comment procéder à la mise à jour vers la dernière version du moteur, consultezExécution d'une mise à jour corrective de la version du moteur d'un cluster.

  • Pour définir le planificateur version 2.0 comme planificateur de requêtes par défaut, vous devez disposer des autorisations IAM pour mettre à jour les groupes de paramètres de cluster.

  • Pour Amazon DocumentDB 8.0, la version 3.0 du planificateur est le planificateur de requêtes par défaut. Consultez Planificateur de requêtes v3 pour plus de détails.

Sélection de la version 2.0 du planificateur de requêtes comme planificateur de requêtes par défaut

Procédez comme suit pour sélectionner 2.0 comme planificateur de requêtes par défaut depuis la console ou l'interface de ligne de commande :

  • Suivez les étapes décrites Modification des paramètres du cluster Amazon DocumentDB pour modifier le groupe de paramètres de votre cluster.

  • Pour le paramètre intitulé « PlannerVersion », remplacez la valeur par 2.0, indiquant la version 2.0 du planificateur.

  • Sélectionnez Appliquer immédiatement (si vous sélectionnez Appliquer au redémarrage, la sélection sera inefficace jusqu'au prochain redémarrage du cluster).

Bonnes pratiques

Pour obtenir les résultats escomptés, appliquez les bonnes pratiques suivantes lors de l'application de la version 2.0 du planificateur :

  • Dans un cluster global, sélectionnez la même plannerVersion valeur (1.0 ou 2.0) dans les groupes de paramètres du cluster pour les deux régions. Notez que la sélection de différentes versions du planificateur dans les régions principales et secondaires peut entraîner un comportement et des performances incohérents des requêtes.

  • La mise à jour vers la version 2.0 du planificateur pendant une fenêtre de maintenance planifiée ou pendant des périodes de trafic réduit sera la solution la moins perturbatrice, car les taux d'erreur peuvent augmenter si la version du planificateur est modifiée alors que les charges de travail sont en cours d'exécution active.

  • La version 2.0 de Planner fonctionne de manière optimale avec la version 5.0 du shell MongoDB.

Limitations

Les limites suivantes s'appliquent à la version 2.0 du planificateur :

  • La version 2.0 du planificateur n'est pas prise en charge dans les clusters élastiques, qui reviendront à la version 1.0 du planificateur.

  • La version 2.0 du planificateur n'est pas prise en charge pour l'agrégation et les commandes distinctes, qui reviendront à la version 1.0 du planificateur.

  • Il n'est pas possible de définir un filtre de cache de plan pour certaines formes de requête. Pour la liste actuelle, voirFormes de requête prises en charge.

Améliorations apportées à la recherche et à la mise à jour

La version 2.0 de Planner optimise les opérations fondamentalesfind, notamment updatedelete, et find-and-modify les commandes. Les sections à onglets suivantes présentent des fonctionnalités améliorées pour les index, ainsi que les améliorations des performances des requêtes apportées à la version 2.0 du planificateur :

Enhanced index support
  • La version 2.0 de Planner ajoute la prise en charge des index pour les opérateurs de négation $nin $ne$not {eq}, notamment$not {in},, et, ainsi que $type et$elemMatch.

    Sample Document: { "x": 10, "y": [1, 2, 3] } db.foo.createIndex({ "x": 1, "y": 1 }) db.foo.find({ "x": {$nin: [20, 30] }}) db.foo.find({"x":{ $type: "string" }}) db.foo.createIndex({"x.y": 1}) db.foo.find({"x":{$elemMatch:{"y":{$elemMatch:{"$gt": 3 }}}}})
  • La version 2.0 de Planner utilise des index fragmentés ou partiels même lorsqu'ils ne $exists sont pas présents dans l'expression de requête.

    Sample Document: {"name": "Bob", "email": "example@fake.com" } Using Planner Version 1.0, you can specify the command as shown below: db.foo.find({email: "example@fake.com", email: {$exists: true}}) Using Planner Version 2.0, you can specify command without $exists: db.foo.find({ email: "example@fake.com" })
  • La version 2.0 de Planner utilisera des index partiels même lorsque la condition de requête ne correspond pas exactement à l'expression du filtre d'index partiel.

    Sample Document: {"name": "Bob", "age": 34} db.foo.createIndex({"age":1},{partialFilterExpression:{"age":{$lt:50}}}) With Planner Version 1.0, index is used only when the query condition meets the partial index filter criterion: db.foo.find({"age":{$lt:50}}) With Planner Version 2.0, index is used even when the query condition doesn’t meet the index criterion: db.foo.find({"age":{$lt:30}})
  • La version 2.0 de Planner utilise une analyse d'index partielle avec les requêtes $elemMatch.

    Sample Document: {"name": "Bob", "age": [34,35,36]} db.foo.createIndex({"age":1},{partialFilterExpression:{"age":{$lt:50,$gt:20}}}) db.foo.find({age:{$elemMatch:{$lt:50,$gt:20}}})
  • La version 2.0 de Planner inclut la prise en charge de l'analyse d'index pour$regex, sans qu'il soit nécessaire $hint de fournir le code de votre application. $regexprend en charge l'index sur les recherches de préfixes uniquement.

    Sample Document: { "x": [1, 2, 3], "y": "apple" } db.foo.createIndex({ "x": 1, "y": 1 }) db.foo.find({"y":{ $regex: "^a" }})
  • La version 2.0 de Planner améliore les performances des requêtes impliquant des index multiclés, avec des conditions d'égalité sur les champs multiclés.

    Sample Document: {"x": [1, 2, 3], "y": 5} db.foo.createIndex({"x": 1, "y":1}) db.foo.find({"x": 2, "y": {$gt: 1}}).limit(1)
  • La version 2.0 de Planner améliore les performances des requêtes impliquant plusieurs filtres, en particulier sur les collections contenant des documents supérieurs à 8 Ko.

    Sample Document: {"x": 2, "y": 4, "z": 9, "t": 99} db.foo.find({$and: [{"x": {$gt : 1}, "y": {$gt : 3}, "z": {$lt : 10}, "t":{$lt : 100}}]})
  • La version 2.0 de Planner améliore les performances des requêtes lors de l'utilisation de $in l'opérateur avec un index composé en supprimant l'étape de tri.

    Sample Document: {"x": 2, "y": 4, "z": 9, "t": 99} db.foo.createIndex({"x":1, "y":1}) db.foo.find({"x":2, "y":$in:[1,2,3,4]}).sort({x:1,y:1})

    Il améliore également les performances des requêtes qui utilisent des index multiclés avec $in des éléments.

    Sample Document: {"x": [1, 2, 3]} db.foo.createIndex({"x": 1}) db.foo.find("x":{$in:[>100 elements]})
Query performance improvements
  • La version 2.0 de Planner améliore les performances des requêtes impliquant plusieurs filtres, en particulier sur les collections contenant des documents supérieurs à 8 Ko.

    Sample Document: {"x": 2, "y": 4, "z": 9, "t": 99} db.foo.find({$and: [{"x": {$gt : 1}, "y": {$gt : 3}, "z": {$lt : 10}, "t":{$lt : 100}}]})
  • La version 2.0 de Planner améliore les performances des requêtes lors de l'utilisation de $in l'opérateur avec un index composé en supprimant l'étape de tri.

    Sample Document: {"x": 2, "y": 4, "z": 9, "t": 99} db.foo.createIndex({"x":1, "y":1}) db.foo.find({"x":2, "y":$in:[1,2,3,4]}).sort({x:1,y:1})

    Il améliore également les performances des requêtes qui utilisent des index multiclés avec $in des éléments.

    Sample Document: {"x": [1, 2, 3]} db.foo.createIndex({"x": 1}) db.foo.find("x":{$in:[>100 elements]})

Planifier les filtres de cache

La version 2.0 de Planner prend en charge les filtres de cache des plans, également appelés filtres d'index, qui vous permettent de restreindre l'ensemble d'index pris en compte par le planificateur pour une forme de requête spécifique. Les filtres sont définis à l'aide d'une commande de base de données et appliqués sur le serveur. Ainsi, si vous rencontrez une régression de requête, vous pouvez l'atténuer sans modifier le code de votre application.

Dans la version 2.0 du planificateur, les filtres de cache des plans s'appliquent aux count commandes find et, à partir d'Amazon DocumentDB 5.0.2 et 8.0.2, également aux commandes updatedelete, et. findAndModify Les aggregate commandes distinct et nécessitent la version 3.0 du planificateur.

Pour plus d'informations sur la référence des commandes, les formes de requête prises en charge, des exemples pratiques et la manière dont les filtres interagissent avec les astuces, consultezPlanifier les filtres de cache.

Différences de comportement potentielles entre les versions 1.0 et 2.0 du planificateur et MongoDB

Dans certains cas extrêmes, il est possible que la version 2.0 du planificateur produise des résultats légèrement différents de ceux de MongoDB. Cette section présente quelques exemples de ces possibilités.

$(update) and $(projection)
  • Dans certains cas, $(projection) les opérateurs $(update) de MongoDB peuvent se comporter différemment par rapport à la version 1.0 du planificateur d'Amazon DocumentDB. Voici quelques exemples :

    db.students_list.insertMany( [ { _id: 5, student_ids: [ 100, 200 ], grades: [ 95, 100 ], grad_year: [ 2024, 2023 ] } ] )
    db.students_list.updateOne({ student_ids: 100, grades: 100, grad_year: 2024 }, { $set: { “grad_year.$”: 2025 } }
    • Planner version 1.0 — Champ de mises à jour 2022

    • MongoDB — Champ de mises à jour 2022

    • Planner version 2.0 — Mises à jour du champ 2021

  • db.col.insert({x:[1,2,3]}) db.col.update({$and:[{x:1},{x:3}]},{$set:{"x.$":500}})
    • Planner version 1.0 — Met à jour aléatoirement le premier élément correspondant

    • MongoDB — Met à jour aléatoirement le premier élément correspondant

    • Planner version 2.0 — N'effectue pas de mises à jour

  • db.col.insert({x:[1,2,3]}) db.col.find()
    • Planner version 1.0 — Sélectionne au hasard l'élément correspondant

    • MongoDB — Sélectionne aléatoirement l'élément correspondant

    • Planner version 2.0 — Ne fait aucune sélection

  • db.col.insert({x:100}) db.col.update({x:100},{x:100})
    • Planner version 1.0 — Changements de comptage modifiés

    • MongoDB — Changements de comptage modifiés

    • Planner version 2.0 — Le nombre de modifications ne change pas lorsqu'il est mis à jour avec la même valeur.

  • Lorsque $(update) l'opérateur est utilisé avec$setOnInsert, la version 1.0 du planificateur et MongoDB génèrent une erreur, mais pas la version 2.0 du planificateur.

  • Le fait de renommer un champ inexistant pour $field génère une erreur dans la version 2.0 du planificateur, mais ne produit aucune mise à jour dans la version 1.0 du planificateur et MongoDB.

Index behavior
  • La version 2.0 du planificateur génère une erreur lorsqu'elle $hint est appliquée avec un index inapproprié, alors que la version 1.0 du planificateur et MongoDB ne le font pas.

    // Insert db.col.insert({x:1}) db.col.insert({x:2}) db.col.insert({x:3}) // Create index on x with partialFilter Expression {x:{$gt:2}} db.col.createIndex({x:1},{partialFilterExpression:{x:{$gt:2}}}) // Mongodb allows hint on the following queries db.col.find({x:1}).hint("x_1") // result is no documents returned because {x:1} is not indexed by the partial index // Without $hint mongo should return {x:1}, thus the difference in result between COLSCAN and IXSCAN DocumentDB will error out when $hint is applied on such cases. db.col.find({x:1}).hint("x_1") Error: error: { "ok" : 0, "operationTime" : Timestamp(1746473021, 1), "code" : 2, "errmsg" : "Cannot use Hint for this Query. Index is multi key index , partial index or sparse index and query is not optimized to use this index." } rs0:PRIMARY> db.runCommand({"planCacheSetFilter": "col", "query": { location: {$nearSphere: {$geometry: {type: "Point", coordinates: [1, 1]}}}}, "indexes": ["name_1"]}) { "ok" : 0, "operationTime" : Timestamp(1750815778, 1), "code" : 303, "errmsg" : "Unsupported query shape for index filter $nearSphere" }
  • $nearne peut pas être utilisé $hint({“$natural”:1}) dans la version 2.0 du planificateur.

    // indexes present are index on x and geo index rs0:PRIMARY> db.usarestaurants.getIndexes() [ { "v" : 4, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "test.usarestaurants" }, { "v" : 4, "key" : { "location" : "2dsphere" }, "name" : "location_2dsphere", "ns" : "test.usarestaurants", "2dsphereIndexVersion" : 1 } ] // Planner Version 2.0 will throw an error when $hint is applied with index "x_1" rs0:PRIMARY> db.usarestaurants.find({ "location":{ "$nearSphere":{ "$geometry":{ "type":"Point", "coordinates":[ -122.3516, 47.6156 ] }, "$minDistance":1, "$maxDistance":2000 } } }, { "name":1 }).hint({"$natural": 1}) Error: error: { "ok" : 0, "operationTime" : Timestamp(1746475524, 1), "code" : 291, "errmsg" : "unable to find index for $geoNear query" } // Planner Version 1.0 and MongoDB will not throw an error db.usarestaurants.find({ "location":{ "$nearSphere":{ "$geometry":{ "type":"Point", "coordinates":[ -122.3516, 47.6156 ] }, "$minDistance":1, "$maxDistance":2000 } } }, { "name":1 }).hint({"$natural": 1}) { "_id" : ObjectId("681918e087dadfd99b7f0172"), "name" : "Noodle House" }
  • Alors que MongoDB prend en charge les analyses complètes des index regex, la version 2.0 du planificateur prend en charge l'analyse des index regex uniquement sur les champs de préfixes.

    // index on x db.col.createIndex({x:1}) // index scan is used only for prefix regexes rs0:PRIMARY> db.col.find({x: /^x/}).explain() { "queryPlanner" : { "plannerVersion" : 2, "namespace" : "test.col", "winningPlan" : { "stage" : "IXSCAN", "indexName" : "x_1", "direction" : "forward", "indexCond" : { "$and" : [ { "x" : { "$regex" : /^x/ } } ] }, "filter" : { "x" : { "$regex" : /^x/ } } } }, "indexFilterSet" : false, "indexFilterApplied" : false, "ok" : 1, "operationTime" : Timestamp(1746474527, 1) } // COLSCAN is used for non-prefix regexes rs0:PRIMARY> db.col.find({x: /x$/}).explain() { "queryPlanner" : { "plannerVersion" : 2, "namespace" : "test.col", "winningPlan" : { "stage" : "COLLSCAN", "filter" : { "x" : { "$regex" : /x$/ } } } }, "indexFilterSet" : false, "indexFilterApplied" : false, "ok" : 1, "operationTime" : Timestamp(1746474575, 1)
  • Il existe certaines différences inhérentes à l'utilisation des filtres de cache des plans avec la version 2.0 du planificateur par rapport à MongoDB. Alors que la version 2.0 du planificateur ne prend pas en charge la spécification de « projection » et de « classement » avec des filtres de cache de plan, MongoDB le fait. Cependant, le filtre d'index MongoDB est uniquement en mémoire et est perdu après le redémarrage. La version 2.0 de Planner conserve les filtres d'index par le biais de redémarrages et de correctifs.

Others
  • Le format des journaux d'audit DML lors de l'utilisation de la version 2.0 du planificateur varie légèrement par rapport à celui de la version 1.0 du planificateur.

    command - db.col.find({x:1}) ************** Audit logs generated ****************** // v1 format for dml audit logs {"atype":"authCheck","ts":1746473479983,"timestamp_utc":"2025-05-05 19:31:19.983","remote_ip":"127.0.0.1:47022","users":[{"user":"serviceadmin","db":"test"}],"param":{"command":"find","ns":"test.col","args":{"batchSize":101,"filter":{"x":1},"find":"col","limit":18446744073709551615,"lsid":{"id":{"$binary":"P6RCGz9ZS4iWBSSHWXW15A==","$type":"4"},"uid":{"$binary":"6Jo8PisnEi3dte03+pJFjdCyn/5cGQL8V2KqaoWsnk8=","$type":"0"}},"maxScan":18446744073709551615,"singleBatch":false,"skip":0,"startTransaction":false},"result":0}} // v2 formal for dml audit logs {"atype":"authCheck","ts":1746473583711,"timestamp_utc":"2025-05-05 19:33:03.711","remote_ip":"127.0.0.1:37754","users":[{"user":"serviceadmin","db":"test"}],"param":{"command":"find","ns":"test.col","args":{"find":"col","filter":{"x":1},"lsid":{"id":{"$binary":"nJ88TGCSSd+BeD2+ZtrhQg==","$type":"4"}},"$db":"test"},"result":0}}
  • La condition de l'indice dans le cadre du plan d'explication :

    rs0:PRIMARY> db.col.createIndex({index1:1}) { "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1, "operationTime" : Timestamp(1761149251, 1) }

    La version 2.0 du planificateur explique la sortie du plan affichant la condition de l'index et le filtre :

    rs0:PRIMARY> db.col.find({$and:[{price:{$eq:300}},{item:{$eq:"apples"}}]}).explain() { "queryPlanner" : { "plannerVersion" : 2, "namespace" : "test.col", "winningPlan" : { "stage" : "IXSCAN", "indexName" : "price_1", "direction" : "forward", "indexCond" : { "$and" : [ { "price" : { "$eq" : 300 } } ] }, "filter" : { "$and" : [ { "item" : { "$eq" : "apples" } } ] } } }, "indexFilterSet" : false, "indexFilterApplied" : false, "ok" : 1, "operationTime" : Timestamp(1761149497, 1) }

    La version 1.0 de Planner explique les résultats du plan :

    rs0:PRIMARY> db.col.find({$and:[{price:{$eq:300}},{item:{$eq:"apples"}}]}).explain() { "queryPlanner" : { "plannerVersion" : 1, "namespace" : "test.col", "winningPlan" : { "stage" : "IXSCAN", "indexName" : "price_1", "direction" : "forward" } }, "ok" : 1, "operationTime" : Timestamp(1761149533, 1) }

La version 2.0 de Planner comble le fossé comportemental avec MongoDB

Dans certains domaines, la version 2.0 du planificateur comble les écarts de comportement par rapport à MongoDB :

  • La version 2.0 de Planner permet de rechercher des index numériques sur des tableaux aplatis pour : $elemMatch

    doc: {"x" : [ [ { "y" : 1 } ] ] } // Planner Version 2 and mongo > db.bar.find({"x.0": {$elemMatch: {y: 1}}}) { "_id" : ObjectId("68192947945e5846634c455a"), "x" : [ [ { "y" : 1 } ] ] } > db.bar.find({"x": {$elemMatch: {"0.y": 1}}}) { "_id" : ObjectId("68192947945e5846634c455a"), "x" : [ [ { "y" : 1 } ] ] } //Whereas Planner Version 1 wouldn't return any results. > db.bar.find({"x.0": {$elemMatch: {y: 1}}}) > db.bar.find({"x": {$elemMatch: {"0.y": 1}}})
  • Alors que la version 1.0 du planificateur excluait les chaînes dans la projection, le comportement de la version 2.0 du planificateur s'aligne sur MongoDB et les traite comme des valeurs littérales »

    // Planner V2/ MongoDB > db.col.find() { "_id" : ObjectId("681537738aa101903ed2fe05"), "x" : 1, "y" : 1 } > db.col.find({},{x:"string"}) { "_id" : ObjectId("681537738aa101903ed2fe05"), "x" : "string" } // Planner V1 treats strings as exclude in projection rs0:PRIMARY> db.col.find() { "_id" : ObjectId("68153744d42969f11d5cca72"), "x" : 1, "y" : 1 } rs0:PRIMARY> db.col.find({},{x:"string"}) { "_id" : ObjectId("68153744d42969f11d5cca72"), "y" : 1 }
  • La version 2.0 de Planner, comme MongoDB, n'autorise pas la projection sur les mêmes champs « x » et « x.a » :

    // Planner version 2/MongoDB will error out > db.col.find() { "_id" : ObjectId("68153da2012265816bc9ba23"), "x" : [ { "a" : 1 }, 3 ] } db.col.find({},{"x.a":1,"x":1}) // error // Planner Version 1 does not error out db.col.find() { "_id" : ObjectId("68153da2012265816bc9ba23"), "x" : [ { "a" : 1 }, 3 ] } db.col.find({},{"x.a":1,"x":1}) { "_id" : ObjectId("68153d60143af947c720d099"), "x" : [ { "a" : 1 }, 3 ] }
  • La version 2.0 de Planner, comme MongoDB, permet la projection sur des sous-documents :

    // Planner Version2/MongoDB supports projections on subdocuments db.col.find() { "_id" : ObjectId("681542d8f35ace71f0a50004"), "x" : [ { "y" : 100 } ] } > db.col.find({},{"x":{"y":1}}) { "_id" : ObjectId("681542b7a22d548e4ac9ddea"), "x" : [ { "y" : 100 } ] } // Planner V1 throws error if projection is subdocument db.col.find() { "_id" : ObjectId("681542d8f35ace71f0a50004"), "x" : [ { "y" : 100 } ] } rs0:PRIMARY> db.col.find({},{"x":{"y":1}}) Error: error: { "ok" : 0, "operationTime" : Timestamp(1746223914, 1), "code" : 2, "errmsg" : "Unknown projection operator y" }
  • Avec Planner version 2.0, comme MongoDB, la projection ne prend pas en charge les champs situés après l'$opérateur :

    // Mongo and Planner Version 2 will error out db.col.find() { "_id" : ObjectId("68155fa812f843439b593f3f"), "x" : [ { "a" : 100 } ] } db.col.find({"x.a":100},{"x.$.a":1}) - // error // v1 will not error out db.col.find() { "_id" : ObjectId("68155fa812f843439b593f3f"), "x" : [ { "a" : 100 } ] } db.col.find({"x.a":100},{"x.$.a":1}) { "_id" : ObjectId("68155dee13b051d58239cd0a"), "x" : [ { "a" : 100 } ] }
  • La version 2.0 de Planner, comme MongoDB, permet $hint d'utiliser :

    // v1 will error out on $hint if there are no filters db.col.find({}).hint("x_1") Error: error: { "ok" : 0, "operationTime" : Timestamp(1746466616, 1), "code" : 2, "errmsg" : "Cannot use Hint for this Query. Index is multi key index , partial index or sparse index and query is not optimized to use this index." } // Mongo and Planner Version 2 will allow $hint usage db.col.find({}).hint("x_1") { "_id" : ObjectId("6818f790d5ba9359d68169cf"), "x" : 1 }