索引类型怎么选
MongoDB 的索引按查询形态分类:单字段与复合索引应对常规过滤与排序,数组字段自动成为多键索引,文本索引支持词项检索,地理索引做距离与区域查询,TTL 索引负责过期清理,此外还有唯一、部分、稀疏、哈希与通配符索引。选型依据是查询模式,而不是越多越好。
基本信息
| 单字段与复合 | { field: 1 } 与 { a: 1, b: -1 },复合索引的字段顺序决定可用范围 |
|---|---|
| 多键 | 数组字段自动成为多键索引,与数组查询配合 |
| 文本与地理 | { field: "text" } 做词项检索,{ loc: "2dsphere" } 做距离与区域查询 |
| 唯一、部分、稀疏 | unique 做约束,partialFilterExpression 只索引子集,sparse 跳过缺失字段 |
| 哈希与通配符 | hashed 用于等值查询与哈希分片,通配符索引应对字段名不固定的子文档 |
典型使用场景
- 按查询模式逐个验证索引效果,而不是凭字段数量堆索引
- 用复合索引同时满足过滤与排序,注意字段顺序
- 用部分索引只索引活跃数据,减少索引体积与写入开销
- 用唯一索引约束业务键,从数据库层面防止重复
- 字段名动态变化时用通配符索引,但要评估索引膨胀
常用创建语句
常用创建语句
// 常见索引类型
db.users.createIndex({ email: 1 }, { unique: true }) // 唯一索引
db.orders.createIndex({ status: 1, createdAt: -1 }) // 复合索引
db.logs.createIndex({ expireAt: 1 }, { expireAfterSeconds: 3600 }) // TTL 索引
db.articles.createIndex({ title: "text", body: "text" }) // 文本索引
db.shops.createIndex({ loc: "2dsphere" }) // 地理索引
db.users.createIndex({ phone: 1 }, { partialFilterExpression: { phone: { $exists: true } } }) // 部分索引
db.events.createIndex({ "attrs.$**": 1 }) // 通配符索引
// 验证某个查询是否命中索引
db.orders.find({ status: "paid" }).explain("executionStats")索引类型与用途
| 类型 | 定义方式 | 适合场景 |
|---|---|---|
| 单字段 | { field: 1 } | 单条件等值与范围过滤 |
| 复合 | { a: 1, b: -1 } | 多条件组合与排序,注意字段顺序 |
| 多键 | 数组字段自动成为多键 | 数组元素匹配 |
| 文本 | { field: "text" } | 词项检索与相关度排序 |
| 地理 | { loc: "2dsphere" } | 距离与区域查询 |
| TTL | 加 expireAfterSeconds | 定时过期清理 |
| 唯一 | 加 unique | 唯一性约束 |
| 部分 | 加 partialFilterExpression | 只索引子集,节省空间 |
| 稀疏 | 加 sparse | 跳过缺失该字段的文档 |
| 哈希 | { user_id: "hashed" } | 等值查询与哈希分片 |
| 通配符 | { "attrs.$**": 1 } | 字段名不固定的子文档 |
生产集合通常是「若干精心设计的复合索引加必要的唯一约束」,而不是索引越多越好;新增索引前先用 explain 确认现有索引确实用不上,避免白白增加写放大。
复合索引的字段顺序决定它能服务哪些查询:等值条件放前面、范围与排序放后面是常见经验,但真正可靠的判断方式仍是用 explain 对比扫描文档数。