|
ts",
"isMultiKey" : false,
"n" : 55555,
"nscannedObjects" : 1000000,
"nscanned" : 1000000,
"nscannedObjectsAllPlans" : 1000000,
"nscannedAllPlans" : 1000000,
"scanAndOrder" : true,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 695,
"indexBounds" : {
"type" : [
[
1,
1
]
],
"sex" : [
[
0,
0
]
]
},
"server" : "node1:27017"
}
看到没,这个查询语句跟上一个创建索引之后的查询出来的结果相差还是很大的,scanAndOrder和millis,时间花费了将近700毫秒,而且在查询完毕之后还要排序,这也太不近人情了,就加了一个排序操作,怎么会让它从白天鹅变成丑小鸭了呢?啊,关键参数就是scanAndOrder,意思就是在内存中把结果排序了嘛,那好啊,既然你如此薄情,那我就建个复合索引来对抗: db.test.ensureIndex({type:1,sex:1,time:-1},{name:'index_tst'})
{
"cursor" : "BtreeCursor index_tst",
"isMultiKey" : false,
"n" : 55555,
"nscannedObjects" : 55555,
"nscanned" : 55555,
"nscannedObjectsAllPlans" : 55555,
"nscannedAllPlans" : 55555,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 126,
"indexBounds" : {
"type" : [
[
1,
1
]
],
"sex" : [
[
0,
0
]
],
"time" : [
[
{
"$maxElement" : 1
},
{
"$minElement" : 1
}
]
]
},
"server" : "node1:27017"
}
看到了吗?各种参数又回到最佳状态了。这时候可能有人会问了,为什么要把time放到索引的最后而不是其它位置呢?其实这在创建索引时是有要求的,即:
-
将等值索引放在最前面
-
尽量将排序字段放在范围字段的前面
-
$nin和$ne跟索引没有关系 接下来我们再给查询语句加条件: db.test.find({type:1,sex:0,id:{$gt:1,$lt:500000}}) 执行计划如下:
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 55555,
"nscannedObjects" : 1000000,
"nscanned" : 1000000,
"nscannedObjectsAllPlans" : 1000000,
"nscannedAllPlans" : 1000000,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 2,
"nChunkSkips" : 0,
"millis" : 553,
"indexBounds" : {
},
"server" : "node1:27017"
} 可以看到,只返回两万多条数据,但是却扫描了整个表,这肯定是很蛋疼的事情嘛,索引走起: db.test.ensureIndex({type:1,sex:1,id:1},{name:'index_tis'})
{
"cursor" : "BtreeCursor index_tis",
"isMultiKey" : false,
"n" : 55555,
"nscannedObjects" : 55555,
"nscanned" : 55555,
"nscannedObjectsAllPlans" : 55555,
"nscannedAllPlans" : 55555,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 137,
"indexBounds" : {
"type" : [
[
1,
1
]
],
"sex" : [
[
0,
0
]
],
"id" : [
[
1,
1000000
]
]
},
"server" : "node1:27017"
} 很显然,这是个非常不错的组合索引,那为何不把id放在其它地方,偏偏放在最后面呢?因为在mongodb中,索引是从左到右执行的,因此显然要从左到右一次过滤最大数量的数据显然type和sex的组合过滤数据量要比id高更多,因为id的忙查率要远高于这两个组合。 接着再把按time排序加上,查询:db.test.find({type:1,sex:1,id:{$gt:0,$lt:1000000}}).sort({time:-1}).explain()
{
"cursor" : "BasicCursor",
"isMultiKey" : false,
"n" : 55556,
"nscannedObjects" : 1000000,
"nscanned" : 1000000,
"nscannedObjectsAllPlans" : 1000000,
"nscannedAllPlans" : 1000000,
"scanAndOrder" : true,
"indexOnly" : false,
"nYields" : 1,
"nChunkSkips" : 0,
"millis" : 725,
"indexBounds" : {
},
"server" : "node1:27017"
} 可以看到,这个查询语句也是极其慢的,而且还要再内存中排序,所以肯定要创建索引了: db.test.ensureIndex({type:1,sex:1,id:1,time:-1},{name:'index_tist'}) 我们先这样创建索引,看看执行计划:
{
"cursor" : "BtreeCursor index_tist",
"isMultiKey" : false,
"n" : 55556,
"ns |