面试问题浓缩总结 面试问题浓缩总结
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • Go
  • Java
  • C/C++
  • JavaScript/HTML
  • MySQL
  • Redis
  • MongoDB
  • 操作系统
  • 计算机网络
  • spring全家桶
  • mybatis
  • 中间件
  • 软件相关
  • 系统相关
  • 算法
  • 数据结构
  • 设计模式
  • CMU硕士经典100题
  • 剑指offer
  • 重点手撕代码
  • 程序员面试金典
  • 3月
  • 4月
  • 智力题
  • 业务问题
  • 一些技术
  • 安全相关
APP下载 (opens new window)
GitHub (opens new window)
  • MySQL

  • Redis

  • MongoDB

    • 面试问题汇总
    • 存储引擎
    • 索引
      • 索引的类型
        • 几大索引类型
        • 慢查询分析
      • 索引的原理
    • 分布式和集群
    • 体系和架构
    • 常用命令
  • 数据库
  • MongoDB
小游
2021-04-06

索引

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
    2
  • explain 分析

  • 分析慢速查询:应用程序设计不合理、数据模型设计有误、硬件配置问题、缺少索引等

  • 解读 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)

编辑 (opens new window)
上次更新: 2021/04/08, 21:41:12
存储引擎
分布式和集群

← 存储引擎 分布式和集群→

Theme by Vdoing | Copyright © 2021-2021 小游
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式