一、引言
好久没有写东西了,MongoDB系列的文章也丢下好长时间了。今天终于有时间了,就写了一篇有关索引的文章。一说到“索引”,用过关系型数据库的人都应该知道它是一个什么东西。当我们要访问的数据量大了的时候,可以通过建立索引来提高查询速度。关系型数据库有“索引”的概念,我们的MongoDB数据库也有索引的概念,今天我就来抛砖引玉,简单的说一说MongoDB文档数据库中的“索引”的概念。
二、简介
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构 。
三、详细操作
1、索引创建
1.1、语法:可以向指定集合中增加一个索引
ensureIndex()方法基本语法格式如下所示:
>db.collectionName.ensureIndex({KEY:1,KEY2:1,...KEYN:1})
说明:语法中 Key-Keyn 值为你要创建的索引字段,1为指定按升序创建索引,如果你想按降序来创建索引指定为-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.2、代码实例
//原始数据 >db.school.find({},{_id:0}); {"name":"liulei","age":"32","sex":"1","address":"hebei"} {"name":"zhangfei","age":"28","sex":"1","address":"shanxi"} {"name":"guanyu","age":"30","sex":"1","address":"shanxi"} {"name":"diaochan","age":"18","sex":"0","address":"guangdong"} //向name字段增加升序索引 >db.school.ensureIndex({"title":1}) { "createdCollectionAutomaticallly":false, "numIndexesBefore":1, "numIndexesAfter":2, "ok":1 } //ensureIndex() 方法中你也可以设置使用多个字段创建索引(关系型数据库中称作复合索引)。 >db.school.ensureIndex({"title":1,"age":-1}) { "createdCollectionAutomaticallly":false, "numIndexesBefore":2, "numIndexesAfter":3, "ok":1 }
2、检索索引
2.1、语法:检索当前指定集合所有的索引
getIndexes()方法基本语法格式如下所示:
>db.collectionName.getIndexes()
说明:会列出该集合内所有的索引。
2.2、代码实例
//原始数据 >db.school.find({},{_id:0}); {"name":"liulei","age":"32","sex":"1","address":"hebei"} {"name":"zhangfei","age":"28","sex":"1","address":"shanxi"} {"name":"guanyu","age":"30","sex":"1","address":"shanxi"} {"name":"diaochan","age":"18","sex":"0","address":"guangdong"} //获取当前school集合里面所有的索引 >db.school.getIndexes(); [ { "v":2, "key":{"_id":1}, "name":"_id_" "ns":"school.school" }, { "v":2, "key":{"name":1}, "name":"name_1" "ns":"school.school" }, { "v":2, "key":{"name":1,"age":-1}, "name":"name_1_age_-1" "ns":"school.school" } ]
3、删除索引
3.1、语法:删除指定集合里面指定名称的索引
dropIndex(INDEX-NAME)方法基本语法格式如下所示:
>db.collectionName.dropIndex(INDEX-NAME)
说明:删除索引的时候必须指定索引的名称。
3.2、语法:删除指定集合里面所有索引
dropIndexes()方法基本语法格式如下所示:
>db.collectionName.dropIndexes()
说明:该方法可以删除指定集合中所有的索引。
3.3、代码实例
//原始数据 >db.school.getIndexes(); [ { "v":2, "key":{"_id":1}, "name":"_id_" "ns":"school.school" }, { "v":2, "key":{"name":1}, "name":"name_1" "ns":"school.school" }, { "v":2, "key":{"name":1,"age":-1}, "name":"name_1_age_-1" "ns":"school.school" } ] //删除名称为是:name_1 的索引 >db.school.dropIndex("name_1"); {"nIndexesWas":3,"ok":1} //当前索引数据 >db.school.getIndexes(); [ { "v":2, "key":{"_id":1}, "name":"_id_" "ns":"school.school" }, { "v":2, "key":{"name":1,"age":-1}, "name":"name_1_age_-1" "ns":"school.school" } ] //删除所有索引数据 >db.school.dropIndexes(); {"nIndexesWas":2,"msg":"non-_id indexes dropped for collection","ok":1} //当前的索引数据 >db.school.getIndexes(); [ { "v":2, "key":{"_id":1}, "name":"_id_" "ns":"school.school" } ]
4、重建索引
4.1、语法:重新建立指定集合中所有的索引
reIndex()方法基本语法格式如下所示:
>db.collectionName.reIndex();
说明:重新建立指定集合的所有索引。
4.2、代码实例
//原始数据 >db.school.find({},{_id:0}); {"name":"liulei","age":"32","sex":"1","address":"hebei"} {"name":"zhangfei","age":"28","sex":"1","address":"shanxi"} {"name":"guanyu","age":"30","sex":"1","address":"shanxi"} {"name":"diaochan","age":"18","sex":"0","address":"guangdong"} //重新创建当前school集合里面所有的索引 >db.school.reIndex(); { "nIndexesWas":3, "nIndexes":3 "indexes":[ { "v":2, "key":{"_id":1}, "name":"_id_" "ns":"school.school" }, { "v":2, "key":{"name":1}, "name":"name_1" "ns":"school.school" }, { "v":2, "key":{"name":1,"age":-1}, "name":"name_1_age_-1" "ns":"school.school" }], "ok":1 }
5、统计指定集合索引文件的大小
5.1、语法:统计指定集合中所有索引文件大大小
totalIndexSize()方法基本语法格式如下所示:
>db.collectionName.totalIndexSize();
说明:统计指定集合中所有索引文件大大小。
5.2、代码实例
//统计school集合中索引文件的大小 >db.school.totalIndexSize(); 49152
四、使用索引的时候注意事项
1、额外开销
每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。所以,如果你很少对集合进行读取操作,建议不使用索引。
2、内存(RAM)使用
由于索引是存储在内存(RAM)中,你应该确保该索引的大小不超过内存的限制。
如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。
3、查询限制
索引不能被以下的查询使用:
正则表达式及非操作符,如 $nin, $not, 等。
算术运算符,如 $mod, 等。
$where 子句
所以,检测你的语句是否使用索引是一个好的习惯,可以用explain来查看。
4、索引键限制
从2.6版本开始,如果现有的索引字段的值超过索引键的限制,MongoDB中不会创建索引。
5、插入文档超过索引键限制
如果文档的索引字段值超过了索引键的限制,MongoDB不会将任何文档转换成索引的集合。与mongorestore和mongoimport工具类似。
6、最大范围
集合中索引不能超过64个,一般一个集合6-9索引就可以了
索引名的长度不能超过128个字符
一个复合索引最多可以有31个字段
五、结束
好了,就是这些了,我这个短短的文章只是起到了一个因子的作用,当然也希望对大家有帮助。我写的这些文章,也记录了我重拾记录的历史,争取在有时间的情况下,把自己的学习历程记录下来,为以后的自己铺平垫路。今天只是简单的讲了Mongodb的索引,如果以后有了新的学习心得,我在补充进来,不忘初心,继续努力吧。