[SERVER-15958] The "isMultiKey" value is not correct in the output of aggregation explain plan Created: 04/Nov/14  Updated: 11/Jul/16  Resolved: 12/Nov/14

Status: Closed
Project: Core Server
Component/s: Aggregation Framework, Diagnostics, Querying
Affects Version/s: 2.6.5
Fix Version/s: 2.6.6, 2.8.0-rc1

Type: Bug Priority: Major - P3
Reporter: Linda Qin Assignee: David Storch
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
is duplicated by SERVER-14628 Aggregation explain "cursor" field tr... Closed
Related
Tested
Operating System: ALL
Backport Completed:
Steps To Reproduce:

> db.version()
2.6.5
> db.test.insert({x:1, y:[2,3]})
WriteResult({ "nInserted" : 1 })
> db.test.ensureIndex({y:1})
{
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1
}
> db.test.find({y:2}).explain()
{
	"cursor" : "BtreeCursor y_1",
	"isMultiKey" : true,
	"n" : 1,
	"nscannedObjects" : 1,
	"nscanned" : 1,
	"nscannedObjectsAllPlans" : 1,
	"nscannedAllPlans" : 1,
	"scanAndOrder" : false,
	"indexOnly" : false,
	"nYields" : 0,
	"nChunkSkips" : 0,
	"millis" : 0,
	"indexBounds" : {
		"y" : [
			[
				2,
				2
			]
		]
	},
	"server" : "LindaQins-MacBook-Pro.local:22222",
	"filterSet" : false
}
> db.test.aggregate([{$match:{y:2}}], {explain:true})
{
	"stages" : [
		{
			"$cursor" : {
				"query" : {
					"y" : 2
				},
				"plan" : {
					"cursor" : "BtreeCursor ",
					"isMultiKey" : false,
					"scanAndOrder" : false,
					"indexBounds" : {
						"y" : [
							[
								2,
								2
							]
						]
					},
					"allPlans" : [
						{
							"cursor" : "BtreeCursor ",
							"isMultiKey" : false,
							"scanAndOrder" : false,
							"indexBounds" : {
								"y" : [
									[
										2,
										2
									]
								]
							}
						}
					]
				}
			}
		}
	],
	"ok" : 1
}

Participants:

 Description   

The $match aggregation pipeline uses a multikey index, however, "isMultiKey" is false in the output of aggregation explain plan.

Also, the index being used ("y_1") is missing in the field ("cursor" : "BtreeCursor "). It would be nice if the output can be ("cursor" : "BtreeCursor y_1").



 Comments   
Comment by Githook User [ 20/Nov/14 ]

Author:

{u'username': u'dstorch', u'name': u'David Storch', u'email': u'david.storch@10gen.com'}

Message: SERVER-15958 initialize IndexScanStats fields isMultiKey and indexName on IndexScan construction

(cherry picked from commit 52db1600fcde4a5b6bd25ed83802d02bde64538c)

Conflicts:
src/mongo/db/exec/index_scan.cpp
Branch: v2.6
https://github.com/mongodb/mongo/commit/671e340cf5a6676fb4008103d3f0e2684354be8f

Comment by Githook User [ 12/Nov/14 ]

Author:

{u'username': u'dstorch', u'name': u'David Storch', u'email': u'david.storch@10gen.com'}

Message: SERVER-15958 initialize IndexScanStats fields isMultiKey and indexName on IndexScan construction
Branch: master
https://github.com/mongodb/mongo/commit/52db1600fcde4a5b6bd25ed83802d02bde64538c

Comment by J Rassi [ 05/Nov/14 ]

linda.qin@10gen.com: the "cursor" reporting error is being tracked by SERVER-14628.

It looks like the "isMultiKey" issue is caused by the fact that the explain machinery is expecting that the given plan has been executed, but the aggregation framework does not execute the given plan before invoking the explain machinery (and, by contrast, the find().explain() path does execute the plan before explaining it). The IndexScanStats::isMultiKey flag only is set on the first call made to IndexScan::work(), so if no call to PlanExecutor::getNext() is made, then this field gets the default value of false.

Possible ways to fix this issue in 2.6.x aggregation:

  • The IndexScan constructor could initialize isMultiKey.
  • DocumentSourceCursor::serialize() could call _runner->getNext() a number of times equal to the batch size before calling _runner->getInfo().
  • the "isMultiKey" field could be removed from the explain output.

This issue has a somewhat wider impact in 2.7.x, as it more broadly affects all uses of the "queryPlanner" explain verbosity (which aggregation uses). My index stats patch (which isn't going in) actually moved initialization of isMultiKey to the IndexScan constructor, so maybe that's the entire fix? As for 2.6.x, I haven't investigated whether it's safe there to access the catalog from the IndexScan constructor, but I can't think of any reasons why not right now.

See the following repro:

> db.serverBuildInfo().version
2.7.9-pre-
> db.serverBuildInfo().gitVersion
2a741dfecb4fa1ee894ddbfc81b21f42687bc46f
> db.foo.drop()
true
> db.foo.ensureIndex({a:1})
{
	"createdCollectionAutomatically" : true,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1
}
> db.foo.insert({a:[1,2]})
WriteResult({ "nInserted" : 1 })
> db.foo.explain("executionStats").find({a:1}).next().queryPlanner
{
	"plannerVersion" : 1,
	"parsedQuery" : {
		"a" : {
			"$eq" : 1
		}
	},
	"winningPlan" : {
		"stage" : "FETCH",
		"inputStage" : {
			"stage" : "IXSCAN",
			"keyPattern" : {
				"a" : 1
			},
			"isMultiKey" : true, // correct
			"direction" : "forward",
			"indexBounds" : {
				"a" : [
					"[1.0, 1.0]"
				]
			}
		}
	},
	"rejectedPlans" : [ ]
}
> db.foo.explain("queryPlanner").find({a:1}).next().queryPlanner
{
	"plannerVersion" : 1,
	"parsedQuery" : {
		"a" : {
			"$eq" : 1
		}
	},
	"winningPlan" : {
		"stage" : "FETCH",
		"inputStage" : {
			"stage" : "IXSCAN",
			"keyPattern" : {
				"a" : 1
			},
			"isMultiKey" : false, // incorrect
			"direction" : "forward",
			"indexBounds" : {
				"a" : [
					"[1.0, 1.0]"
				]
			}
		}
	},
	"rejectedPlans" : [ ]
}
>

Assigning to david.storch.

Generated at Thu Feb 08 03:39:31 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.