索引可以提高查询速度,但是会降低写入速度。在Mongo中索引可以按字段升序或者降序创建,便于排序,索引默认使用btree组织索引文件,当然也允许使用hash索引。
Mongo在创建集合时,默认会为_id键创建索引,索引信息均保存在system.indexes中。
//explain可以输出查询信息 uindex是user文档的一个字段,从1开始到10000依次递增 db.user.find({"uindex":100}).explain() 这时候会输出: { "cursor":"BasicCursor", "nscanedObjects":100 ... }
BasicCursor代表没有使用索引,nscanedObjects代表扫描了多少次。在没有使用索引时,按照{"name":"lisi"}
要求依次查找,直到查找到要求的结果。
添加索引后查询:
db.user.ensureIndex({uindex:1}) db.user.find({"uindex":100}).explain()
此时输出的结果是:
{ "cursor":"BtreeCursor uindex", "nscanedObjects":1 ... }
# 查看索引 db.user.getIndexes() //_id是默认索引 # 创建索引 1代表正向 -1代表反向(在磁盘上倒序) db.user.ensureIndex({name: -1}) # 删除索引 需要带上类型 db.user.dropIndex({name: -1}) db.user.dropIndexes() //删除所有非_id索引
多列索引:
# 同时为name,uindex建立索引,这有别于分别为name,uindex各添加索引 # 多列索引的意义在于将name和uindex绑定到了一起,适用于查询时候经常同时查询name和uindex db.user.ensureIndex({name:1,uindex:-1})
子文档索引
# 有这样的复杂文档 {name:"zs",info:{age:16, from:"北京"}} {name:"lisi",info:{age:22, from:"上海"}} # 需求,查询来自北京的 db.user.find(info:{from:"北京"})是无法查到的 db.user.ensureIndex({info.from: 1})
上述创建的索引都是普通索引,在创建索引时候可以指定一些参数:
# 创建唯一索引 索引值不能重复,即下列的uindex值不能重复 db.user.ensureIndex({uindex: 1},{unique:true}) # 创建稀疏索引 # 如果一个文档内被索引的字段不存在(值为null),仍然会建立索引 # 创建稀疏索引,则遇到上述情况后,不会建立索引 db.user.ensureIndex({uindex: 1},{sparse:true}) # 创建哈希索引 # 哈希有一个内部函数,存储数据时候使用该函数创建位置,比btree(基于二叉树)更快的找到数据,但是hash计算的位置具有散列的特性,所以如果按照范围查找会受到影响(因为会在硬盘上随机查找) db.user.ensureIndex({uindex: "hashed"})
MongoDB在1.4中引入了地理空间索引,可以索引基于位置的数据,用于提供地图定位服务。
一个表经过多次修改后,会导致表的文件产生空洞,索引文件也是如此,可以通过重建所有索引来减少索引碎片,提升索引效率。
db.user.reIndex()
如果某个查询没有使用索引,我们可以通过hint命令强制使用索引查询
db.user.find().hint("name":"lisi").explain()
在mysql中,可以使用慢查询日志来作为优化数据库的依据,在Mongo中可以使用MongoDB Database Profiler。
profiler开启方式:
方式一:启动时添加 --profile参数 方式二:客户端调用db.setProfilingLevel()方法 db.setProfilingLevel(2,10) 参数一:0代表不开启,1为记录慢命令(默认大于100ms),2记录所有命令 参数二:可选,代表多少速度的慢命令被记录,在方式一种设置方式为 参数 --slowms
慢命令的日志记录在system.profile中,查询方式:
show profile # 查询最近的5条慢命令 db.system.profile.find({millis: {$gt: 5}}) # 按需查询慢日志
合理建立索引需要知道:
哪些键需要索引
每个键的索引方向
有没有不同的键排列可以使常用的数据更多的保留在内存中
比如有一个用户评论的集合,包含字段username,content,date,一般情况下搜索的条件都是username和date,所以需要索引的键确立了。
db.content.ensureIndex({"username": 1, "date": 1})
这时候,username和date按照升序排列,评论一般date要求是最新的,date应该是降序,索引需要修改为:
db.content.ensureIndex({"username": 1, "date": -1})
如果我们要查询用户和日期,取出该用户的最近的评论,Mongo按照索引键的前后顺序先查询到对应的用户名,再在同组用户名中去查询最近的评论,如果要查询的用户每次都不同,则内存中存放的索引页每次都要替换掉,如果调整下索引的前后顺序,date放在前面,那么内存中会有限保存最近几天的用户索引,无论查哪个用户最近的评论,都不需要替换内存中的索引页。
db.content.ensureIndex({"date": -1, "username": 1 })
本文地址:https://www.stayed.cn/item/388
转载请注明出处。
本站部分内容来源于网络,如侵犯到您的权益,请 联系我