mongoDB 索引(四)

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构

1.ensureIndex() 方法
MongoDB使用 ensureIndex() 方法来创建索引。

语法
ensureIndex()方法基本语法格式如下所示:

 >db.COLLECTION_NAME.ensureIndex({KEY:1})
语法中 Key 值为你要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-1即可。

实例
数据准备index.js,里面有

for(var i = 0 ; i<200000 ;i++){
    db.books.insert({number:i,name:i+"book"})
}
1.先检验一下查询性能
使用load加载js文件
> load("D:/install/MongoDB/test/index.js")
true
> var start = new Date()
>             db.books.find({number:65871})
{ "_id" : ObjectId("5a3a1b3290cf1481126d353e"), "number" : 65871, "name" : "65871book" }
>             var end = new Date()
>             end - start
74
结果74

2.为number 创建索引

 db.books.ensureIndex({number:1})
3.再执行第一部的代码可以看出有数量级的性能提升
> var start = new Date()
>             db.books.find({number:65871})
{ "_id" : ObjectId("5a3a1b3290cf1481126d353e"), "number" : 65871, "name" : "65871book" }
>             var end = new Date()
>             end - start
6
ensureIndex() 方法中你也可以设置使用多个字段创建索引(关系型数据库中称作复合索引)

db.col.ensureIndex({"title":1,"description":-1})  
ensureIndex() 接收可选参数,可选参数列表如下:

Parameter    Type    Description
background    Boolean    建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 "background" 可选参数。 "background" 默认值为false。
unique    Boolean    建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
name    string    索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
dropDups    Boolean    在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.
sparse    Boolean    对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
expireAfterSeconds    integer    指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
v    index version    索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weights    document    索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
default_language    string    对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_override    string    对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.
实例
1.1在后台创建索引:
 db.values.ensureIndex({open: 1, close: 1}, {background: true})  
通过在创建索引时加background:true 的选项,让创建工作在后台执行

1.2创建索引同时指定索引的名字
db.books.ensureIndex({name:-1},{name:”bookname”})
 1.3  建立唯一索引,解决文档books不能插入重复的数值
 db.books.ensureIndex({name:-1},{unique:true})

 试验

> db.books.ensureIndex({name:1},{unique:true})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}
> db.books.insert({name:"1book"})
WriteResult({
        "nInserted" : 0,
        "writeError" : {
                "code" : 11000,
                "errmsg" : "E11000 duplicate key error collection: admin.books index: name_1 dup key: { : \"1book\" }"
        }
})

1.4.踢出重复值
      建立唯一索引之前已经有重复数值如何处理

 db.books.ensureIndex({name:-1},{unique:true,dropDups:true})
1.5.强制查询使用指定的索引Hint
    db.books.find({name:"1book",number:1}).hint({name:-1})


1.6 查看本次查询使用那个索引和查询数据的状态信息 Expain
> db.books.find({name:"1book"}).explain()
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "admin.books",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "name" : {
                                "$eq" : "1book"
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "name" : 1
                                },
                                "indexName" : "name_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "name" : [ ]
                                },
                                "isUnique" : true,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "name" : [
                                                "[\"1book\", \"1book\"]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "DESKTOP-VKU59R5",
                "port" : 27017,
                "version" : "3.4.10",
                "gitVersion" : "078f28920cb24de0dd479b5ea6c66c644f6326e9"
        },
        "ok" : 1
}
 
“cursor” : “BtreeCursor name_-1“ 使用索引
“nscanned” : 1 查到几个文档
“millis” : 0 查询时间0是很不错的性能


1.7 查看索引
 mongoDB提供了查看索引信息的方法:

 getIndexes()方法可以用来查看集合的所有索引,

> db.books.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "admin.books"
        },
        {
                "v" : 2,
                "key" : {
                        "number" : 1
                },
                "name" : "number_1",
                "ns" : "admin.books"
        },
        {
                "v" : 2,
                "unique" : true,
                "key" : {
                        "name" : 1
                },
                "name" : "name_1",
                "ns" : "admin.books"
        }
]
totalIndexSize()查看集合索引的总大小,

> db.books.totalIndexSize()
4321280
db.system.indexes.find()查看数据库中所有索引信息。
1.8. 删除索引
不在需要的索引,我们可以将其删除。删除索引时,可以删除集合中的某一索引,可以删除全部索引。

 删除指定的索引dropIndex()

db.COLLECTION_NAME.dropIndex("INDEX-NAME")
如,删除集合sites中名为"name_1_domain_-1"的索引:

> db.sites.dropIndex("name_1_domain_-1")
{ "nIndexesWas" : 2, "ok" : 1 }
删除所有索引dropIndexes()

db.COLLECTION_NAME.dropIndexes()
如,删除集合sites中所有的索引:

> db.sites.dropIndexes()
{
  "nIndexesWas" : 1,
  "msg" : "non-_id indexes dropped for collection",
  "ok" : 1
}


2.空间索引
mongoDB提供强大的空间索引可以查询出一定范围的地理坐标.看例子, 准备数据map.json

> load("D:/install/MongoDB/test/map.json")
true
1.查询出距离点(70,180)最近的3个点

        添加2D索引

> db.map.ensureIndex({"gis":"2d"},{min:-1,max:204})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
 默认会建立一个[-180,180]之间的2D索引,查询点(70,180)最近的3个点

> db.map.find({"gis":{$near:[70,180]}},{gis:1,_id:0}).limit(3)
{ "gis" : { "x" : 70, "y" : 180 } }
{ "gis" : { "x" : 75, "y" : 180 } }
{ "gis" : { "x" : 65, "y" : 185 } }

2.查询以点(50,50)和点(190,190)为对角线的正方形中的所有的点

> db.map.find({gis:{"$within":{$box:[[50,50],[190,190]]}}},{_id:0,gis:1})
{ "gis" : { "x" : 50, "y" : 50 } }
{ "gis" : { "x" : 50, "y" : 50 } }
{ "gis" : { "x" : 60, "y" : 55 } }
{ "gis" : { "x" : 55, "y" : 80 } }
{ "gis" : { "x" : 65, "y" : 80 } }
{ "gis" : { "x" : 65, "y" : 185 } }
{ "gis" : { "x" : 70, "y" : 180 } }
{ "gis" : { "x" : 75, "y" : 180 } }
{ "gis" : { "x" : 185, "y" : 150 } }
{ "gis" : { "x" : 185, "y" : 185 } }

3.查询出以圆心为(56,80)半径为50规则下的圆心面积中的点

> db.map.find({gis:{$within:{$center:[[56,80],50]}}},{_id:0,gis:1})
{ "gis" : { "x" : 50, "y" : 50 } }
{ "gis" : { "x" : 50, "y" : 50 } }
{ "gis" : { "x" : 60, "y" : 55 } }
{ "gis" : { "x" : 55, "y" : 80 } }
{ "gis" : { "x" : 65, "y" : 80 } }
3.索引使用需要注意的地方
         1.创建索引的时候注意1是正序创建索引-1是倒序创建索引

         2.索引的创建在提高查询性能的同事会影响插入的性能, 对于经常查询少插入的文档可以考虑用索引

         3.符合索引要注意索引的先后顺序

         4.每个键全建立索引不一定就能提高性能呢, 索引不是万能的

         5.在做排序工作的时候如果是超大数据量也可以考虑加上索引, 用来提高排序的性能

参考:http://www.mongodb.org.cn/tutorial/18.html
--------------------- 
作者:青鸟&飞鱼 
来源:CSDN 
原文:https://blog.csdn.net/u014401141/article/details/78854952 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/Allen_Walker_QAQ/article/details/86545988