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() 分析执行计划、选择合适的索引类型、科学管理索引生命周期,可以有效平衡查询性能与系统开销。

相关推荐
我叫唧唧波16 小时前
Python+AI 全栈学习笔记
人工智能·python·学习
不会就选b17 小时前
MySQL之视图
数据库·mysql
城北徐宫17 小时前
Linux信号深度解剖:5种产生、3张表、4次切换
linux·c++·学习
>no problem<17 小时前
基于cola5.0的基础设施层的多数据库切换方案思路
数据库·spring boot·mybatisplus·cola5.0·数据库迁移适配
OceanBase数据库官方博客17 小时前
OceanBase 赋能央国企:从发电到用电的全链路业务承载
数据库·oceanbase
三品吉他手会点灯18 小时前
C语言学习笔记 - 43.运算符与表达式 - 运算符1 - 运算符的分类和简单介绍
c语言·笔记·学习·算法
瀚高PG实验室18 小时前
pgsql-ogr-fdw
数据库·postgresql·瀚高数据库·highgo
IvorySQL18 小时前
PostgreSQL 技术日报 (6月5日)|PG19 Beta1 上线,PGConf.PL 2026开启征稿
数据库·postgresql·区块链
abcy07121319 小时前
pycharm python sqlalchemy mysql增删改查实例csdn
数据库·oracle
无风听海19 小时前
IndexedDB 深度指南 浏览器中的事务型对象数据库
前端·数据库