-
Type: Improvement
-
Resolution: Duplicate
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
-
Query Optimization
Presumably since the index can't fully cover/answer the query, we don't consider any relevant indexes when comparing to sub-objects:
> db.test.drop() true > db.test.createIndex({"a.b": 1, "a.c": 1}) { "numIndexesBefore" : 1, "numIndexesAfter" : 2, "createdCollectionAutomatically" : true, "ok" : 1 } > db.test.insert({a: {b: 1, c: 2}}) WriteResult({ "nInserted" : 1 }) > db.test.find({a: {b: 1, c: 2}}).explain() { "explainVersion" : "1", "queryPlanner" : { "namespace" : "test.test", "parsedQuery" : { "a" : { "$eq" : { "b" : 1, "c" : 2 } } }, "indexFilterSet" : false, "queryHash" : "18A4453A", "planCacheKey" : "E34C8026", "optimizationTimeMillis" : 0, "maxIndexedOrSolutionsReached" : false, "maxIndexedAndSolutionsReached" : false, "maxScansToExplodeReached" : false, "prunedSimilarIndexes" : false, "winningPlan" : { "isCached" : false, "stage" : "COLLSCAN", "filter" : { "a" : { "$eq" : { "b" : 1, "c" : 2 } } }, "direction" : "forward" }, "rejectedPlans" : [ ] }, "command" : { "find" : "test", "filter" : { "a" : { "b" : 1, "c" : 2 } }, "$db" : "test" }, "serverInfo" : { "host" : "ip-10-128-16-109", "port" : 27017, "version" : "8.0.0-alpha2", "gitVersion" : "unknown" }, "serverParameters" : { "internalQueryFacetBufferSizeBytes" : 104857600, "internalQueryFacetMaxOutputDocSizeBytes" : 104857600, "internalLookupStageIntermediateDocumentMaxSizeBytes" : 104857600, "internalDocumentSourceGroupMaxMemoryBytes" : 104857600, "internalQueryMaxBlockingSortMemoryUsageBytes" : 104857600, "internalQueryProhibitBlockingMergeOnMongoS" : 0, "internalQueryMaxAddToSetBytes" : 104857600, "internalDocumentSourceSetWindowFieldsMaxMemoryBytes" : 104857600, "internalQueryFrameworkControl" : "trySbeRestricted" }, "ok" : 1 }
However it's possible to generate exact index bounds with a residual equality match on the entire sub-object, which could be far more performant than a collection scan if the predicate is highly selective. Worth noting that in the above example, switching to dotted path notation gives slightly different semantics (allows other fields in the matching sub-object) and will use the index.
- duplicates
-
SERVER-2953 Use dotted indexes for embedded document queries
- Backlog