[SERVER-27646] covered index should be used when null inequality is in the query and index is not multikey Created: 11/Jan/17  Updated: 29/Nov/22  Resolved: 20/Jun/18

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: None
Fix Version/s: 4.1.1

Type: Bug Priority: Major - P3
Reporter: Asya Kamsky Assignee: Charlie Swanson
Resolution: Done Votes: 5
Labels: bi-performance, mock-pm, storch
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
is duplicated by SERVER-44931 Covered queries do not work when $ne/... Closed
Problem/Incident
Related
is related to SERVER-18861 Queries matching null value should be... Backlog
Backwards Compatibility: Fully Compatible
Operating System: ALL
Sprint: Query 2018-05-21, Query 2018-06-04, Query 2018-06-18, Query 2018-07-02
Participants:
Case:
Linked BF Score: 0

 Description   

Having index on

{a:1, b:1}

here are some plans:
Good:

> db.ix.explain().find({a:1,b:2},{_id:0,a:1})
{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "test.ix",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"$and" : [
				{
					"a" : {
						"$eq" : 1
					}
				},
				{
					"b" : {
						"$eq" : 2
					}
				}
			]
		},
		"winningPlan" : {
			"stage" : "PROJECTION",
			"transformBy" : {
				"_id" : 0,
				"a" : 1
			},
			"inputStage" : {
				"stage" : "IXSCAN",
				"keyPattern" : {
					"a" : 1,
					"b" : 1
				},
				"indexName" : "a_1_b_1",
				"isMultiKey" : false,
				"multiKeyPaths" : {
					"a" : [ ],
					"b" : [ ]
				},
				"isUnique" : false,
				"isSparse" : false,
				"isPartial" : false,
				"indexVersion" : 2,
				"direction" : "forward",
				"indexBounds" : {
					"a" : [
						"[1.0, 1.0]"
					],
					"b" : [
						"[2.0, 2.0]"
					]
				}
			}
		},
		"rejectedPlans" : [ ]
	},
	"serverInfo" : {
		"host" : "altoros4",
		"port" : 34001,
		"version" : "3.5.1-89-g7b68733",
		"gitVersion" : "7b68733fae7ce8d91f9a5fda67b9972c15a20ef0"
	},
	"ok" : 1
}

Good:

> db.ix.explain().find({a:1,b:{$ne:2}},{_id:0,a:1})
{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "test.ix",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"$and" : [
				{
					"a" : {
						"$eq" : 1
					}
				},
				{
					"$nor" : [
						{
							"b" : {
								"$eq" : 2
							}
						}
					]
				}
			]
		},
		"winningPlan" : {
			"stage" : "PROJECTION",
			"transformBy" : {
				"_id" : 0,
				"a" : 1
			},
			"inputStage" : {
				"stage" : "IXSCAN",
				"keyPattern" : {
					"a" : 1,
					"b" : 1
				},
				"indexName" : "a_1_b_1",
				"isMultiKey" : false,
				"multiKeyPaths" : {
					"a" : [ ],
					"b" : [ ]
				},
				"isUnique" : false,
				"isSparse" : false,
				"isPartial" : false,
				"indexVersion" : 2,
				"direction" : "forward",
				"indexBounds" : {
					"a" : [
						"[1.0, 1.0]"
					],
					"b" : [
						"[MinKey, 2.0)",
						"(2.0, MaxKey]"
					]
				}
			}
		},
		"rejectedPlans" : [ ]
	},
	"serverInfo" : {
		"host" : "altoros4",
		"port" : 34001,
		"version" : "3.5.1-89-g7b68733",
		"gitVersion" : "7b68733fae7ce8d91f9a5fda67b9972c15a20ef0"
	},
	"ok" : 1
}

Bad:

> db.ix.explain().find({a:1,b:{$ne:null}},{_id:0,a:1})
{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "test.ix",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"$and" : [
				{
					"a" : {
						"$eq" : 1
					}
				},
				{
					"$nor" : [
						{
							"b" : {
								"$eq" : null
							}
						}
					]
				}
			]
		},
		"winningPlan" : {
			"stage" : "PROJECTION",
			"transformBy" : {
				"_id" : 0,
				"a" : 1
			},
			"inputStage" : {
				"stage" : "FETCH",
				"filter" : {
					"$nor" : [
						{
							"b" : {
								"$eq" : null
							}
						}
					]
				},
				"inputStage" : {
					"stage" : "IXSCAN",
					"keyPattern" : {
						"a" : 1,
						"b" : 1
					},
					"indexName" : "a_1_b_1",
					"isMultiKey" : false,
					"multiKeyPaths" : {
						"a" : [ ],
						"b" : [ ]
					},
					"isUnique" : false,
					"isSparse" : false,
					"isPartial" : false,
					"indexVersion" : 2,
					"direction" : "forward",
					"indexBounds" : {
						"a" : [
							"[1.0, 1.0]"
						],
						"b" : [
							"[MinKey, null)",
							"(null, MaxKey]"
						]
					}
				}
			}
		},
		"rejectedPlans" : [ ]
	},
	"serverInfo" : {
		"host" : "altoros4",
		"port" : 34001,
		"version" : "3.5.1-89-g7b68733",
		"gitVersion" : "7b68733fae7ce8d91f9a5fda67b9972c15a20ef0"
	},
	"ok" : 1
}

Why is there a FETCH to compare b!=null? Seems like a bug.



 Comments   
Comment by Githook User [ 20/Jun/18 ]

Author:

{'username': 'cswanson310', 'name': 'Charlie Swanson', 'email': 'charlie.swanson@mongodb.com'}

Message: SERVER-27646 Build index bounds for {$ne: null} predicates
Branch: master
https://github.com/mongodb/mongo/commit/1a18c8f8aec34b43553fe4d7961350d1a7a6ada4

Comment by Asya Kamsky [ 20/Jan/17 ]

Until SERVER-2104 is resolved, this request may only be feasible for non-dotted fields.

Generated at Thu Feb 08 04:15:46 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.