MongoDB实战篇(七):使用索引

第一部分 插入测试数据

#时间稍长

for(var i = 0; i < 200000; i++){    db.numbers.insert({"num": i}); }

验证结果

> db.numbers.find().count()
200000

第二部分 索引前奏

2.1 monogo关键字explain()

explain()可以查看我们执行命令的内部实现,那么我们先看一下,再没有加索引之前,查询一条数据所需要的时间/扫描等字段

没有对比就没有伤害

没有伤害哪来的动力

首先我们查阅官网中对explain()的介绍,在此它有个参数--verbose[冗长],往下看,发现verbose中又有三个可选参数

1. queryPlanner: 默认model, 也就是执行的计划;
2. executionStats: 打印执行的状态;
3. allPlansExecution: 打印所有的执行的状态.

返回的结果又有哪些呢?真是一个问题接着一个问题

继续往下走,摘录一段英文

Output

cursor.explain() operations can return information regarding:

1. queryPlanner, which details the plan selected by the query optimizer and lists the rejected plans;
2. executionStats, which details the execution of the winning plan and the rejected plans; and
3. serverInfo, which provides information on the MongoDB instance.

也就是最多返回三个大的字段,

1. queryPlanner: 查询优化器选择的计划细节,列出了拒绝计划;
2. executionStats: 成功的执行计划细节和拒绝计划;
3. serverInfo: 提供了MongoDB实例的信息。

Mongo官网explain返回说明

有了之上的explain()的主要的使用说明, 那么就可以继续往下继续了.

第三部分 索引

3.1 查询

未加索引的查询

#插叙最后3条数据
> db.numbers.find({"num": {"$gt": 199996}}).explain("executionStats") {    
   "queryPlanner" : {        
   "plannerVersion" : 1,        
   "namespace" : "test.numbers",        
   "indexFilterSet" : false,        
   "parsedQuery" : {            
   "num" : {                
       "$gt" : 199996            } },        
"winningPlan" : {    
   #全文扫描    "stage" : "COLLSCAN",            
   "filter" : {                
       "num" : {                    
           "$gt" : 199996                }            },            
       "direction" : "forward"        },              
   "rejectedPlans" : [ ]    },    
"executionStats" : {        
"executionSuccess" : true,            #返回3个字段        "nReturned" : 3,    #花费时间[毫秒]        "executionTimeMillis" : 92,    #扫描到的索引        "totalKeysExamined" : 0,    #与之前返回字段[nscannedObjects]一致,    #查询的个数        "totalDocsExamined" : 200000,                "executionStages" : {    #全文扫描            "stage" : "COLLSCAN",            "
           filter" : {                
           "num" : {                    
               "$gt" : 199996                }            },           
       "nReturned" : 3,            
       ## 该查询根据index去检索获取具体数据的时间        "executionTimeMillisEstimate" : 47,            
       "works" : 200002,            
       "advanced" : 3,            
       "needTime" : 199998,            
       "needYield" : 0,            
       "saveState" : 1562,            
       "restoreState" : 1562,            
       "isEOF" : 1,            
       "invalidates" : 0,            
       "direction" : "forward",            
       "docsExamined" : 200000        }    },        "serverInfo" : {        
   "host" : "huanghaowei.local",        
   "port" : 27017,        
   "version" : "3.4.0",        
   "gitVersion" : "f4240c60f005be757399042dc12f6addbc3170c1"    },    
"ok" : 1 }
3.2 添加索引
> db.numbers.ensureIndex({"num": 1})
{    
   "createdCollectionAutomatically" : false,    
   "numIndexesBefore" : 1,    
   "numIndexesAfter" : 2,    
   "ok" : 1 } > db.numbers.getIndexes() [    {        
       "v" : 2,        
       "key" : {            
           "_id" : 1        },        
       "name" : "_id_",        
       "ns" : "test.numbers"    },    {        
       "v" : 2,        
       "key" : {            
           "num" : 1        },        
       "name" : "num_1",        
       "ns" : "test.numbers"    } ] >
3.3 验证

其中关于时间的字段少了不是一点的量,当然你也会发现其中,多了好多个字段,先不说其他的,这个时间量就完全可以俘获你的芳心吧 -.__.-

> db.numbers.find({"num": {"$gt": 199996}}).explain("executionStats")
{    
   "queryPlanner" : {        
   "plannerVersion" : 1,        
   "namespace" : "test.numbers",        
   "indexFilterSet" : false,        
   "parsedQuery" : {            
   "num" : {                
       "$gt" : 199996            }        },        
   "winningPlan" : {            
       "stage" : "FETCH",            
       "inputStage" : {            #索引扫描                "stage" : "IXSCAN",                
               "keyPattern" : {                    
                   "num" : 1                },                
       "indexName" : "num_1",                
       "isMultiKey" : false,                
   "multiKeyPaths" : {                    
       "num" : [ ]                },                
   "isUnique" : false,                
   "isSparse" : false,                
   "isPartial" : false,                
   "indexVersion" : 2,                
   "direction" : "forward",                
   "indexBounds" : {                    
           "num" : [                        
               "(199996.0, inf.0]"                    ]                }            }        },        
   "rejectedPlans" : [ ]    },    
   "executionStats" : {        
   "executionSuccess" : true,        
   "nReturned" : 3,    #可以对比一下这几个字段    "executionTimeMillis" : 7,    #仅此为我们需要的数据条数    #nReturned=totalKeysExamined=totalDocsExamined(需要具体情况具体分析)    "totalKeysExamined" : 3,        
   "totalDocsExamined" : 3,            "executionStages" : {            
           "stage" : "FETCH",            
           "nReturned" : 3,            
           "executionTimeMillisEstimate" : 0,            
           "works" : 4,            
           "advanced" : 3,            
           "needTime" : 0,            
           "needYield" : 0,            
           "saveState" : 0,            
           "restoreState" : 0,            
           "isEOF" : 1,            
           "invalidates" : 0,            
           "docsExamined" : 3,            
           "alreadyHasObj" : 0,            
           "inputStage" : {        
               ##索引扫描                "stage" : "IXSCAN",                
               "nReturned" : 3,                
               "executionTimeMillisEstimate" : 0,                
               "works" : 4,                
               "advanced" : 3,                
               "needTime" : 0,                
               "needYield" : 0,                
               "saveState" : 0,                
               "restoreState" : 0,                
               "isEOF" : 1,                
               "invalidates" : 0,                
               "keyPattern" : {                    
                   "num" : 1                },                
               "indexName" : "num_1",                
               "isMultiKey" : false,                
               "multiKeyPaths" : {                    
                   "num" : [ ]                },                
               "isUnique" : false,                
               "isSparse" : false,                
               "isPartial" : false,                
               "indexVersion" : 2,                
               "direction" : "forward",                
               "indexBounds" : {                    
                   "num" : [                        
                       "(199996.0, inf.0]"                    ]                },                
               "keysExamined" : 3,                
               "seeks" : 1,                
               "dupsTested" : 0,                
               "dupsDropped" : 0,                
               "seenInvalidated" : 0            }        }    },    "serverInfo" : {        ....            },    "ok" : 1 } >
3.4 删除索引

不在需要的索引,我们可以将其删除。删除索引时,可以删除集合中的某一索引,可以删除全部索引。

3.4.1 删除指定的索引dropIndex()
db.COLLECTION_NAME.dropIndex("INDEX-NAME")

删除指定的索引

db.numbers.dropIndex("num")

删除所有索引dropIndexes()

> db.numbers.dropIndexes()

相对数据集与复杂程度都属于入门,下篇继续.


上一篇:explain详解


下一篇:遇到应付你的面试官你怎么办?