索引
MongoDB也是有索引的
索引是对数据库一列或多列值进行排序的存储结构,底层一般是一种树状结构,没有索引查询会进行全表扫描,数据量大的时候会严重降低效率。MongoDB 索引和关系型数据库相同,默认情况下 MongoDB 在一个集合创建时就对 _id 创建了唯一索引。
# 索引的类型
# 几大索引类型
- 单键索引 (Single Field)
- 过期索引TTL ( Time To Live)
- 复合索引(Compound Index)
- 多键索引(Multikey indexes)
- 地理空间索引(Geospatial Index)
- 全文索引
- 哈希索引 (Hashed Index)
下面对这些索引进行简单介绍
单键索引 就是单值索引,支持所有类型的单个字段索引,并且可以在文档的任何字段上定义, 对于单个字段索引,索引键的排序顺序无关紧要,因为 MongoDB 可以在任一方向读取索引。 单个例上创建索引
db.集合名.createIndex({"字段名":排序方式}) # 1升序。-1降序 db.集合名.getIndexes()
1
2过期索引 是一种特殊的索引,支持文档在一段时间后自动删除,目前过期索引只能在单个字段上建立,并且类型必须是日期类型。
# expireAfterSeconds:过期时间 db.集合名.createIndex({"日期字段":排序方式}, {expireAfterSeconds: 秒数})
1
2复合索引 复合索引支持基于多个字段的索引; 制作复合索引时要注意的重要事项包括:字段顺序与索引方向。这个类似于mysql的联合索引。
db.集合名.createIndex( { "字段名1" : 排序方式, "字段名2" : 排序方式 } ) # 字段顺序 db.集合名.find({"字段名1":'xx'}) # 启用复合索引
1
2
3复合索引可以参考一下:MongoDB 复合索引_乐沙弥的世界-CSDN博客_mongodb 复合索引 (opens new window)
多键索引 针对数组,MongoDB 支持针对数组中每一个element 创建索引,包括 strings、numbers、nested documents;
地理空间索引 针对地理空间坐标数据创建索引; 2dsphere 索引,用于存储和查找球面上的点; 2d 索引,用于存储和查找平面上的点;
全文索引 string 内容的分词查询,支持任意属性值为 string 或 string 数组,一个集合仅支持最多一个Text Index,另外中文分词不理想,推荐ES;
db.集合名.createIndex({"字段": "text"}) db.集合名.find({"$text": {"$search": "张"}})
1
2哈希索引 针对属性的哈希值进行索引查询,当要使用 Hashed index 时,MongoDB 能够自动的计算 hash 值,无需程序计算 hash 值,hash index 仅支持单个字段等于查询,不支持范围查询;
db.集合名.createIndex({"字段": "hashed"})
1
# 慢查询分析
主要步骤如下
开启内置的查询分析器,记录读写操作效率
db.setProfilingLevel(n,m) # n的取值可选0,1,2(一般设置为1) # 0表示不记录 # 1表示记录慢速操作,如果值为1,m不能为空,单位为ms,用于定义慢速查询的阈值 # 2表示记录所有的读写操作 db.setProfilingLevel(1,500)
1
2
3
4
5查询监控结果
# 导出最慢的三个 db.system.profile.find().sort({millis:-1}).limit(3)
1
2explain 分析
分析慢速查询:应用程序设计不合理、数据模型设计有误、硬件配置问题、缺少索引等
解读 explain 结果,确定是否缺少索引
# 索引的原理
。。。差点被误导了,可能在之前是用的B-树,但是WiredTiger引擎默认的是B+树
耗时一上午检索,找到了几种mongodb使用B树的"强行"解释,我将其归为如下: 既然是非sql数据库,就应该好好利用其支持文本\复杂数据类型的优势,通过表结构的设计,保证数据库的使用者,通过单条查询就能拿到数据,而B树的遍历查询效率虽然不如B+树,但是由于非叶子节点直接就能拿到并返回数据,因此单条查询速度是快于B树的
以下是本人观点: B树的单条查询确实是会更快,但是以本人所经历的项目经验来说,mongodb的表不会都是单条查询的场景,更多的使用场景还是基于几个属性的遍历,当然这可以通过创建复合索引去加快查找速度,然而创建多个索引,本身就会极大的降低数据库写的性能,创建多个索引之后读的性能也不会对比B+树有更多的优势。 综上,如果本人作为引擎的开发者,会选择B+树作为实现索引的数据结构,尽管这牺牲了一部分单条查询的性能,但是常用场景下查询的性能更为可靠。
看这篇mongodb的索引实现该用B树还是B+树 - SegmentFault 思否 (opens new window)
参考:
『浅入浅出』MongoDB 和 WiredTiger - 面向信仰编程 (draveness.me) (opens new window)