2
votes

MongoDB récupère-t-il tout le document même si un seul champ est projeté?

J'ai une collection MongoDB pour les données météorologiques avec chaque document composé d'environ 50 champs de paramètres météorologiques différents. Exemple simple ci-dessous:

db.weather.find({},{ temp: 1})

Si je n'ai besoin que d'un seul champ de tous les documents, disons temp , ma requête serait la suivante:

{
"wind":7,
"swell":6,
"temp":32,
...
"50th_field":32
}

Donc, en interne, MongoDB doit-il récupérer l'intégralité du document pour un seul champ qui a été demandé (projeté)? Ne serait-ce pas une opération coûteuse?

J'ai essayé MongoDB Compass pour comparer les horaires, mais le temps requis était <1 ms, donc je n'ai pas pu comprendre.


0 commentaires

3 Réponses :


1
votes

Oui. Voici comment l'éviter:

  1. créer un index sur temp
  2. Utilisez find(Temp)
  3. désactiver _id (nécessaire).

Courir:

db.coll.find({ temp:{ $ne:null }},{ temp:1, _id:0 })`

{} déclenche collscan car l'algorithme tente de faire correspondre les champs de requête avec le projet

Avec {temp}, {temp, _id:0} il dit: "Oh, j'ai seulement besoin de temp".

Il devrait également être judicieux de dire que {}, {temp, _id:0} n'a besoin que d'index, mais ce n'est pas le cas.


0 commentaires

0
votes

Fondamentalement, l'utilisation de la projection avec des champs de limitation est toujours plus rapide que de récupérer le document complet, vous pouvez même utiliser l'index couvert pour éviter d'examiner les documents (pas d'E / S de disque) pour améliorer les performances de l'archive.

Vérifiez les totalDocsExamined d' executionStats de la démo ci-dessous, le totalDocsExamined était de 0! mais vous devez supprimer le champ _id dans la projection car il n'est pas inclus dans l'index.

Voir aussi: https://docs.mongodb.com/manual/core/query-optimization/#covered-query

> db.test.insertOne({name: 'TJT'})
{
  "acknowledged" : true,
  "insertedId" : ObjectId("5faa0c8469dffee69357dde3")
}
> db.test.createIndex({name: 1})
{
  "createdCollectionAutomatically" : false,
  "numIndexesBefore" : 1,
  "numIndexesAfter" : 2,
  "ok" : 1
}

db.test.explain('executionStats').find({name: 'TJT'}, {_id: 0, name: 1})
{
  "queryPlanner" : {
    "plannerVersion" : 1,
    "namespace" : "memo.test",
    "indexFilterSet" : false,
    "parsedQuery" : {
      "name" : {
        "$eq" : "TJT"
      }
    },
    "winningPlan" : {
      "stage" : "PROJECTION",
      "transformBy" : {
        "_id" : 0,
        "name" : 1
      },
      "inputStage" : {
        "stage" : "IXSCAN",
        "keyPattern" : {
          "name" : 1
        },
        "indexName" : "name_1",
        "isMultiKey" : false,
        "multiKeyPaths" : {
          "name" : [ ]
        },
        "isUnique" : false,
        "isSparse" : false,
        "isPartial" : false,
        "indexVersion" : 2,
        "direction" : "forward",
        "indexBounds" : {
          "name" : [
            "[\"TJT\", \"TJT\"]"
          ]
        }
      }
    },
    "rejectedPlans" : [ ]
  },
  "executionStats" : {
    "executionSuccess" : true,
    "nReturned" : 1,
    "executionTimeMillis" : 0,
    "totalKeysExamined" : 1,
    "totalDocsExamined" : 0,
    "executionStages" : {
      "stage" : "PROJECTION",
      "nReturned" : 1,
      "executionTimeMillisEstimate" : 0,
      "works" : 2,
      "advanced" : 1,
      "needTime" : 0,
      "needYield" : 0,
      "saveState" : 0,
      "restoreState" : 0,
      "isEOF" : 1,
      "invalidates" : 0,
      "transformBy" : {
        "_id" : 0,
        "name" : 1
      },
      "inputStage" : {
        "stage" : "IXSCAN",
        "nReturned" : 1,
        "executionTimeMillisEstimate" : 0,
        "works" : 2,
        "advanced" : 1,
        "needTime" : 0,
        "needYield" : 0,
        "saveState" : 0,
        "restoreState" : 0,
        "isEOF" : 1,
        "invalidates" : 0,
        "keyPattern" : {
          "name" : 1
        },
        "indexName" : "name_1",
        "isMultiKey" : false,
        "multiKeyPaths" : {
          "name" : [ ]
        },
        "isUnique" : false,
        "isSparse" : false,
        "isPartial" : false,
        "indexVersion" : 2,
        "direction" : "forward",
        "indexBounds" : {
          "name" : [
            "[\"TJT\", \"TJT\"]"
          ]
        },
        "keysExamined" : 1,
        "seeks" : 1,
        "dupsTested" : 0,
        "dupsDropped" : 0,
        "seenInvalidated" : 0
      }
    }
  }
}


0 commentaires

1
votes

MonogDB lira toutes les données, mais seul le champ temp (et _id ) sera transmis sur votre réseau au client. Si votre document est plutôt volumineux, les performances globales devraient être meilleures lorsque vous projetez uniquement les champs dont vous avez besoin.


0 commentaires