MongoDB入门学习教程,从入门到精通,MongoDB索引(5)

MongoDB索引

一、索引简介

1.1 索引的概念
  • 索引 是一种特殊的数据结构,存储在内存中,用于提高查询效率。
  • MongoDB 中索引使用 B-Tree 结构(默认),支持高效的范围查询和排序。
  • 索引类似于书籍的目录,能快速定位到数据所在位置,避免全表扫描。
1.2 索引的作用
  • 加速查询:尤其是对大量数据的查询、排序、分组等操作。
  • 唯一性约束:通过唯一索引保证字段值不重复。
  • 覆盖查询:当查询的字段全部在索引中时,可以直接从索引返回结果,无需访问文档。
1.3 索引的代价
  • 占用存储空间:每个索引都会占用额外的磁盘和内存空间。
  • 影响写入性能:插入、更新、删除操作时,需要同步维护索引,导致写操作变慢。
  • 增加内存压力:索引应尽量常驻内存,否则会影响性能。

二、explain输出

2.1 explain() 方法
  • 用于分析查询的执行计划,帮助判断查询是否使用了索引。
  • 语法:db.collection.find().explain("executionStats")
2.2 explain 的三种模式
模式 说明
queryPlanner 只返回查询计划,不实际执行
executionStats 返回查询计划并执行,显示执行统计信息
allPlansExecution 返回所有候选执行计划的详细信息
2.3 关键输出字段解读
字段 含义
stage 执行阶段,如 COLLSCAN(全表扫描)、IXSCAN(索引扫描)、FETCH(回表读取文档)
nReturned 返回的文档数量
totalDocsExamined 扫描的文档总数
totalKeysExamined 扫描的索引条目数
indexName 使用的索引名称
winningPlan 最终选择的执行计划
2.4 性能分析原则
  • 理想情况totalKeysExamined ≈ nReturned,且使用 IXSCAN
  • 需优化情况totalDocsExamined 远大于 nReturned,说明未有效使用索引。

三、何时不使用索引

3.1 不适合使用索引的场景
场景 原因
集合很小 全表扫描比索引查找更快,索引反而增加开销
查询返回大部分数据 索引+回表可能比全表扫描更慢
频繁更新的字段 索引维护成本高
低基数字段 如性别、布尔值等,索引区分度低,效率提升有限
查询使用正则表达式(非前缀) /.*abc/ 无法利用索引
大量写操作场景 索引会显著降低写入性能
3.2 如何判断是否使用索引
  • 使用 explain() 分析执行计划。
  • 如果 stageCOLLSCAN,说明未使用索引。
  • 结合业务读写比例,权衡是否建立索引。

四、索引类型

4.1 单字段索引
  • 最基础的索引类型,针对单个字段建立。
  • 示例:db.users.createIndex({name: 1})
4.2 复合索引
  • 针对多个字段建立的索引,顺序非常重要。
  • 遵循 ESR 原则:等值查询(Equality) → 排序字段(Sort) → 范围查询(Range)
  • 示例:db.users.createIndex({age: 1, name: -1})
4.3 多键索引
  • 用于数组字段,MongoDB 自动为数组每个元素创建索引。
  • 示例:db.articles.createIndex({tags: 1})
4.4 唯一索引
  • 确保字段值唯一,不允许重复。
  • 示例:db.users.createIndex({email: 1}, {unique: true})
4.5 稀疏索引
  • 只索引包含该字段的文档,适用于字段缺失较多的集合。
  • 示例:db.users.createIndex({email: 1}, {sparse: true})
4.6 文本索引
  • 支持字符串内容的全文检索,可对多个字段建立。
  • 示例:db.articles.createIndex({content: "text", title: "text"})
4.7 地理空间索引
  • 支持地理坐标查询,如 2dsphere(球面)和 2d(平面)。
  • 示例:db.places.createIndex({location: "2dsphere"})
4.8 哈希索引
  • 用于分片键,支持等值查询,不支持范围查询。
  • 示例:db.users.createIndex({user_id: "hashed"})
4.9 TTL索引
  • 自动删除过期文档,常用于日志、会话数据。
  • 示例:db.sessions.createIndex({createdAt: 1}, {expireAfterSeconds: 3600})

五、索引管理

5.1 创建索引
javascript 复制代码
// 单字段索引
db.collection.createIndex({field: 1})

// 复合索引
db.collection.createIndex({field1: 1, field2: -1})

// 带选项的索引
db.collection.createIndex({field: 1}, {unique: true, background: true})
5.2 查看索引
javascript 复制代码
// 查看集合所有索引
db.collection.getIndexes()

// 查看索引大小
db.collection.stats().indexSizes
5.3 删除索引
javascript 复制代码
// 删除指定索引
db.collection.dropIndex("index_name")

// 删除所有非 _id 索引
db.collection.dropIndexes()
5.4 索引构建方式
方式 说明
background: true 后台构建,不阻塞读写,但速度较慢(早期版本)
默认(前台) 阻塞所有读写操作,适合维护窗口执行
滚动索引构建 在副本集中逐个节点构建,减少影响
5.5 索引优化建议
  • 避免冗余索引 :如已有 {a:1, b:1},则 {a:1} 是冗余的。
  • 使用覆盖查询 :尽量让查询字段全部在索引中,避免 FETCH
  • 监控索引使用情况 :通过 $indexStatsexplain() 分析未使用的索引。
  • 定期重建索引:对于频繁更新的集合,索引碎片可能影响性能。

总结

MongoDB 索引是提升查询性能的关键工具,但并非所有场景都适合使用。合理设计索引需要结合查询模式、数据分布、读写比例等因素。通过 explain() 分析执行计划、选择合适的索引类型、科学管理索引生命周期,可以有效平衡查询性能与系统开销。

相关推荐
火星机器人life2 小时前
turtlebot3 Ubuntu 20.04 + ROS2 Foxy+Gazebo 11.15.1 环境下编译运行
数据库·ubuntu·mfc
zuowei28892 小时前
MySQL输入密码后闪退?
数据库·mysql·adb
tianyuanwo2 小时前
CentOS 8 部署 MySQL 数据库详尽操作手册
数据库·mysql·centos
星星也在雾里2 小时前
Dify配置PostgreSQL数据库连接详细教程
数据库
NULL指向我2 小时前
信号处理学习笔记4:动态调整系数的一阶低通滤波
笔记·学习·信号处理
云边有个稻草人2 小时前
MySQL 监控实战:mysql_exporter 部署与远程监控实现
数据库·mysql
未来转换2 小时前
Python 框架 Django 从入门到精通
数据库·python·django
前端飞行手册2 小时前
electron应用开发模板,集成多种解决方案
前端·javascript·学习·electron·前端框架·vue
LSL666_2 小时前
MybatisPlus——代码生成器
数据库·mybatisplus