📖 1. 索引基础

  • 默认索引_id 字段自带唯一索引。

  • 单字段索引:对一个字段建索引。

  • 复合索引:多个字段组合建索引。

  • 多键索引:数组字段建索引(数组里的每个值都会建索引)。

  • 唯一索引:字段值必须唯一。

  • TTL 索引:让数据过期自动删除(常用于日志、session)。

  • 部分索引 / 稀疏索引:只索引符合条件的文档。

  • 全文索引:支持文本搜索。


📖 2. 建索引语法

// 单字段索引 db.users.createIndex({ email: 1 }) // 复合索引(age 升序, created_at 降序) db.users.createIndex({ age: 1, created_at: -1 }) // 唯一索引 db.users.createIndex({ email: 1 }, { unique: true }) // 部分索引(只给 active=true 的文档建索引) db.users.createIndex( { last_login: 1 }, { partialFilterExpression: { active: true } } ) // TTL 索引(login_time 30 天后过期) db.sessions.createIndex( { login_time: 1 }, { expireAfterSeconds: 30*24*3600 } )

📖 3. 索引设计规范

✅ 基本原则

  1. 高频查询的字段必须建索引

    • 比如 email(登录用)、created_at(分页用)、article_id(查询文章评论)。

  2. 避免给低选择性字段建索引

    • genderstatus(只有 0/1),建索引没意义,因为匹配结果太多,MongoDB 还是要全表扫描。

  3. 复合索引遵循“最左前缀原则”

    • 索引 {a:1, b:1, c:1},支持:

      • a

      • a, b

      • a, b, c

    • 但不支持单独 bc

  4. 避免过多索引

    • 每个索引会增加写入成本(insert/update/delete 都要更新索引)。

    • 一般来说,一个 collection 不要超过 5–10 个索引。

  5. 区分排序和范围查询

    • 如果有 range(如 age > 30),后面的索引字段不能再用于排序。

    • 所以复合索引要 carefully 按查询习惯设计。

  6. 考虑 TTL 和稀疏索引

    • 日志/临时数据用 TTL;

    • 可选字段(如 mobile)用 sparse/partial index。


📖 4. 实战案例

案例 1:用户表

{ "_id": ObjectId("..."), "name": "Alice", "email": "[email protected]", "age": 25, "mobile": "13800000000", "login_time": ISODate("2023-01-01T10:00:00Z"), "active": true }

索引设计

  • 登录查找 → email 唯一索引

db.users.createIndex({ email: 1 }, { unique: true })
  • 查询最近活跃用户 → 复合索引

db.users.createIndex({ active: 1, login_time: -1 })
  • 清理过期 session → TTL 索引

db.users.createIndex({ login_time: 1 }, { expireAfterSeconds: 2592000 }) // 30天

案例 2:文章 & 评论(独立 collection)

comments 文档

{ "_id": ObjectId("..."), "article_id": ObjectId("..."), "user": "Bob", "text": "不错", "created_at": ISODate("2023-01-01T12:00:00Z") }

索引设计

  • 查询某篇文章的评论 → article_id 索引

db.comments.createIndex({ article_id: 1 })
  • 查询文章最新评论(分页) → 复合索引

db.comments.createIndex({ article_id: 1, created_at: -1 })
  • 查询某个用户的评论 → user 索引

db.comments.createIndex({ user: 1 })

案例 3:电商订单表

order 文档

{ "_id": ObjectId("..."), "user_id": ObjectId("..."), "status": "paid", "total": 100, "created_at": ISODate("2023-01-01T12:00:00Z") }

索引设计

  • 查询用户订单 → user_id + created_at

db.orders.createIndex({ user_id: 1, created_at: -1 })
  • 按状态统计订单 → status

db.orders.createIndex({ status: 1 })

📖 5. 索引调优方法

  • db.collection.getIndexes() → 查看现有索引

  • db.collection.dropIndex("indexName") → 删除无用索引

  • db.collection.find(query).explain("executionStats") → 分析查询是否用到了索引


✅ 总结

  • 建索引要根据查询场景(不要乱建)

  • 复合索引要按查询顺序设计(最左前缀)

  • 数组字段建索引会自动变成多键索引

  • 大数据量表要考虑复合索引 + 分页优化

  • 日志/临时数据用 TTL 索引

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部