I saw a PPT about MongoDB deep indexing a few days ago.
MongoDB indexing: the details
You can see the range and consistency of compound indexes from the beginning and end. On the 129th page of the PPT, review this example. insert nine data records into a collection, as shown below:
> db.good.find(){ "_id" : ObjectId("4e8d629d8ad8bdf2ed6c1990"), "x" : 1, "y" : "b" }{ "_id" : ObjectId("4e8d62a38ad8bdf2ed6c1991"), "x" : 3, "y" : "d" }{ "_id" : ObjectId("4e8d62ad8ad8bdf2ed6c1992"), "x" : 4, "y" : "g" }{ "_id" : ObjectId("4e8d62b28ad8bdf2ed6c1993"), "x" : 5, "y" : "c" }{ "_id" : ObjectId("4e8d62ba8ad8bdf2ed6c1994"), "x" : 6, "y" : "a" }{ "_id" : ObjectId("4e8d62c18ad8bdf2ed6c1995"), "x" : 7, "y" : "e" }{ "_id" : ObjectId("4e8d62ce8ad8bdf2ed6c1996"), "x" : 8, "y" : "c" }{ "_id" : ObjectId("4e8d62d38ad8bdf2ed6c1997"), "x" : 9, "y" : "f" }{ "_id" : ObjectId("4e8d719a6cee6416a5a75a43"), "x" : 5, "y" : "d" }
Then perform a joint index on X and Y.
db.good.ensureIndex({x:1,y:1})
Let's perform this search.
> db.good.find({x:{$gte:4}, y:'c'}).explain(){"cursor" : "BtreeCursor x_1_y_1","nscanned" : 7,"nscannedObjects" : 2,"n" : 2,"millis" : 0,"nYields" : 0,"nChunkSkips" : 0,"isMultiKey" : false,"indexOnly" : false,"indexBounds" : {"x" : [[4,1.7976931348623157e+308]],"y" : [["c","c"]]}}
We can see that nscanned is very high! N is only 2. There is such a sentence on the official website:
IfNscannedIs
Much higherNreturned,
The database is scanning into objects to find the target objects. Consider creating an index to improve this.
Here, nscanned can be considered as the number of scanned records. n is the number of returned records.
Let's take a look at nscanned: 7 in combination with the PPT:
This is the B-Tree Index Tree of MongoDB, becauseX> = 4 & Y = 'C ',So first select left branch search, and left branch search for 4/g and 5/C,(5/C)And then search for 7/e, 6/A, 8/C, 9/F,(8/C meets the conditions). Any conforming X will be checked.
Extension:
After reading the PPT, I ended up here. In this case, the efficiency was not optimistic. So I thought a little bit about it. In this tree, y contains only two nodes, that is to say, since it is a "and", you only need to filter out y first, and the number of searches is greatly halved.
We will create basic indexes on Y.
db.good.ensureIndex({y:1})
In this way, if y is first searched, only two searches are performed. Check the actual situation:
> db.good.find({x:{$gte:4}, y:'c'}).explain(){"cursor" : "BtreeCursor y_1","nscanned" : 2,"nscannedObjects" : 2,"n" : 2,"millis" : 0,"nYields" : 0,"nChunkSkips" : 0,"isMultiKey" : false,"indexOnly" : false,"indexBounds" : {"y" : [["c","c"]]}}
As expected, the basic index is used directly.