?
MongoDB中的索引和其他数据库索引类似,也是使用B-Tree结构。MongoDB的索引是在collection级别上的,并且支持在任何列或者集合内的文档的子列中创建索引。
?
下面是官方给出的一个使用索引查询和排序的一个结构图。
?
所有的MongoDB集合默认都有一个唯一索引在字段“_id”上,如果应用程序没有为 “_id”列定义一个值,MongoDB将创建一个带有ObjectId值的列。(ObjectId是基于 时间、计算机ID、进程ID、本地进程计数器 生成的)
?
MongoDB 同样支持在一列或多列上创建升序或降序索引。
MongoDB还可以创建 多键索引、数组索引、空间索引、text索引、哈希索引,其属性可以是唯一性索引、稀疏性索引、TTL(time to live)索引。
?
索引的限制:
索引名称不能超过128个字符
每个集合不能超过64个索引
复合索引不能超过31列
?
| MongoDB 索引语法 |
|
| db.collection.createIndex({
db.collection.ensureIndex({
? db.collection.createIndex( { "filed": sort } ) db.collection.createIndex( { "filed": sort , "filed2": sort } ) ? db.tab.ensureIndex({"id":1}) db.tab.ensureIndex({"id":1} ,{ name:"id_ind"}) db.tab.ensureIndex({"id":1,"name":1},{background:1,unique:1}) db.tab.ensureIndex( { "id" : "hashed" }) ? |
创建索引(两种方法) ? ? filed :为键列 sort :为排序。1 为升序;-1为降序。 ? 创建单列索引 创建索引并给定索引名称 后台创建唯一的复合索引 创建哈希索引 (更多参数 看文章底部) |
| db.tab.indexStats( { index: "id_ind" } ) db.runCommand( { indexStats: "tab", index: "id_ind" } ) db.tab.getIndexes() db.system.indexes.find() |
(前2个似乎不能用,官方文档解释) (not intended for production deployments) 查看索引 |
| db.tab.totalIndexSize(); |
查看索引大小 |
| db.tab.reIndex() db.runCommand({reIndex:"tab"}) |
重建索引 |
| db.tab.dropIndex(
db.tab.dropIndex("id_1") db.tab.dropIndexes() |
删除索引
删除所有索引(注意!) |
| ? |
? |
?
?
索引性能测试:
?
查看索引是否生效,分析查询性能有没有提高。先插入10万数据到集合tab
?
for(var i=0;1<=100000;i++){
var value=parseInt(i*Math.random());
db.tab.insert({"id":i,"name":"kk"+i,"value":value});
}
?
不知道是不是虚拟机的原因,插入了10分钟都未完成!~
自己又打开文件夹查看,一直进不去文件夹。结果客户端连接断开了!~查看服务竟然停了!
?
重启服务,进去查看行数:96万!(过后再查看吧!就用这数据测试了!)
db.tab.find().count()
?
AnalyzeQuery Performance :http://docs.mongodb.org/manual/tutorial/analyze-query-plan/
| 分析函数 |
|
| db.tab.find({"name":"kk50000"}).explain() |
查询name=”kk50000”的执行分析 |
| db.tab.find({"name":"kk50000"}).explain("queryPlanner") db.tab.find({"name":"kk50000"}).explain("Verbosity") db.tab.find({"name":"kk50000"}).explain("executionStats") db.tab.find({"name":"kk50000"}).explain("allPlansExecution") |
这3种方法执行结果完全包括上面这种的结果 |
| db.tab.find({"name":"kk50000"}).explain() 结果做分析: |
|
| "cursor" : "BasicCursor", "isMultiKey" : false, "n" : 1, "nscannedObjects" : 966423, "nscanned" : 966423, "nscannedObjectsAllPlans" : 966423, "nscannedAllPlans" : 966423, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 7555, "nChunkSkips" : 0, "millis" : 4677, "server" : "kk-ad:27017", "filterSet" : false |
游标类型。BasicCurso(扫描), BtreeCursor(索引) 是否多键(组合)索引 返回行数 扫描行数 扫描行数 所有计划扫描的次数 所有计划扫描的次数 是否在内存中排序 ? ? ? 耗时(毫秒) 服务器 ? |
?
现在创建索引:
db.tab.createIndex({"name":1})
?
| db.tab.find({"name":"kk50000"}).explain() 使用索引的结果 |
|
| "cursor" : "BtreeCursor name_1", "isMultiKey" : false, "n" : 1, "nscannedObjects" : 1, "nscanned" : 1, "nscannedObjectsAllPlans" : 1, "nscannedAllPlans" : 1, "scanAndOrder" : false, "indexOnly" : false, "nYields" : 0, "nChunkSkips" : 0, "millis" : 1, "indexBounds" : { "name" : [ [ "kk50000", "kk50000" ] ] }, "server" : "kk-ad:27017", "filterSet" : false |
游标使用索引BtreeCursor = name_1 ? ? ? ? ? ? ? ? ? ? 耗时:1毫秒 ? ? ? ? ? ? ? ? ? ? |
?
?
上面可以看到,没使用索引时,耗时4677毫秒,使用索引后,1毫秒!~并且不用全文档扫描。
?
索引提示(hint),当前collection创建的索引:
db.tab.ensureIndex({"id":1} ,{name:"id_ind"})
db.tab.ensureIndex({"id":1,"name":1},{background:1,unique:1