https://mongoplayground.net/p/2CHyeuaG0y0
db.test.aggregate([
{
$match: {
$or: [
{
cheese: {
"$exists": true
}
},
{
cheese: {
"$exists": false
}
}
]
}
}
]).explain()
According to the explain output, it is collection scan, despite an index on cheese
.
Can someone explain why the index isn't used here?
That query would perform worse using an index scan than a collection scan.
Both the index and the collection are B-tree-link structures. When the query executor uses an index, it looks up the value of the indexed key in the index B-tree and gets back the key for the document in the collection. It then looks up that key in the collection to fetch the document.
Using an index can perform better than a collection scan in 2 ways:
In the case where the query read all of the documents in the collection, using an index would mean fetching each value from the index to get the key, and then using the key to fetch the document from the collection, i.e. 2 fetches per document returned. This makes a collection scan the more efficient option for queries that read more than 50-75% of the documents in a collection, depending on size.
The query planner identified that query was essentially WHERE 1=1
and selected the appropriate plan.
Note that adding a sort stage to that aggregation causes it to choose to use the index: https://mongoplayground.net/p/Zz_1ZLFlJfc