简体   繁体   中英

MongoDb query and indexOnly=false

Executing the next query (with fields: {_id: 1}):

{ 
  "namespace": "default", 
  "active": true, 
  "searchable": true, 
  "type": "H",
  "keywords.extended": /^a/, 
}

In a collection with 2.200.000 docs (matching namespace 200.000 docs) and documents like:

{
  "active" : true,
  "keywords" : {
    "extended" : ["lorem", "ipsum", "sit", "amet"]
  },
  "namespace" : "rsvcom",
  "searchable" : true,
  "type" : "H"
}

With the index:

{ 
  "namespace": 1, 
  "active": 1, 
  "searchable": 1, 
  "type": 1, 
  "keywords.extended": 1 
}

I'm never getting the indexOnly=true executing "find" or "counts".

  1. It's possible to optimize the way I query this collection?
  2. It's possible to do a count that uses only the index and takes less than 1ms?

Here is the explain with a limit of 5000:

说明

You will not get an indexOnly explain here for three reasons:

  1. you are not specifying that only fields in the index be returned. Covered index query must have a projection so that the index can be used both for filtering and getting back the values queried.

  2. you are using a multiKey index. You cannot have an indexOnly query as in MongoDB multiKey indexes don't contain information as to which field is the array so a document look-up is necessary.

  3. you have embedded field(s) in the document/query. MongoDB cannot determine from the index whether the embedded field is a subdocument or an array element so it will have to look up the document itself.

There is another reason this won't be a particularly speedy query - you are using a regular expression. While left anchored regular expressions will be able to use an index (where the regex is the last field) it won't be as fast a look-up as equality (the same way a range query is not as efficient as an equality query).

Project the result to return only fields that are part of the indexes.

You will get covered indexes indexOnly=true only if you do a projection that eliminates all the fields that are not part of the indexes, from the result; in your case, the subdoc fields (keywords) for example. Explanation: one gets indexOnly=true when the result of the query can be fully determined by the indexes, meaning that all the data to be returned by the query can be completely calculated using only the indexes.

In your special case, there are two things that may prevent it: - If you do not project, mongo does not know upfront that there is no other field in the subdoc apart from the array; Schema-less db. - even if mongo new that there is no other field, I am not sure that computing the array field from indexes will be less expensive (in term of computation) than going an pick the full doc from the db. Anyway, I do not know how mongo does in that case.

EDIT: As noted by @Sammaye in the comment below, covered index will not work with dotted fields, as noted in this JIRA Ticket


That's because, the query is probably getting the _id operator as well in the result. Try modifying your find query to include a projection criteria to explicitly include the fields you want in the result and suppress the _id field:

db.collection.find(
{ 
  "namespace": "default", 
  "active": true, 
  "searchable": true, 
  "type": "H",
  "keywords.extended": /^a/ 
},
{ 
  _id : 0,
  "namespace": 1, 
  "active": 1, 
  "searchable": 1, 
  "type": 1,
  "keywords.extended": 1 
}
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM