🔹 1. 复合索引(Compound Index)

👉 定义:对多个字段建立的索引,例如:

db.users.createIndex({ age: 1, created_at: -1 })

规则:最左前缀原则

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

    • {a}

    • {a, b}

    • {a, b, c}

  • 不支持 {b}{c} 单独查询。

案例:订单表

{ "user_id": 123, "status": "paid", "created_at": ISODate("2023-01-01") }

常见查询:

  • 查询某个用户的订单 → user_id

  • 查询用户最近订单 → user_id + created_at

  • 按状态统计订单 → status

索引设计:

db.orders.createIndex({ user_id: 1, created_at: -1 }) db.orders.createIndex({ status: 1 })

📌 注意
如果写成 {created_at: -1, user_id: 1},就没法支持 "user_id=xx 且按时间排序" 的查询。


🔹 2. 多键索引(Multikey Index)

👉 定义:当索引字段是 数组 时,MongoDB 会自动创建 多键索引,对数组里的每个元素建索引。

案例:文章评论

{ "title": "MongoDB 索引", "tags": ["database", "nosql", "performance"] }

索引:

db.articles.createIndex({ tags: 1 })

查询:

db.articles.find({ tags: "nosql" })

👉 直接走多键索引。

⚠️ 限制:

  1. 一个查询最多只能涉及一个多键索引

    • 如果有两个数组字段同时出现在查询条件里,索引可能失效。

    • 例:{ tags: "nosql", comments.user: "Alice" }

  2. 多键索引不能保证数组内元素的组合唯一性

    • 比如 {tags: ["a","b"]}{tags:["b","a"]},都会被索引成两个值。

优化建议:

  • 如果数组数据量特别大,考虑拆成独立 collection,而不是用多键索引。

  • 多键索引适合标签、分类这种数据量较小的数组。


🔹 3. 大数据量表的索引

当表数据量上百万甚至上亿时,索引设计更重要:

案例:日志表

{ "level": "ERROR", "service": "user-api", "message": "xxx", "created_at": ISODate("2023-01-01T12:00:00Z") }

常见查询场景:

  • 查某个服务的日志(按时间范围)

  • 查最新错误日志

  • 自动清理 30 天前的数据

索引设计:

// 查询某个服务日志 + 时间范围 db.logs.createIndex({ service: 1, created_at: -1 }) // 按 level + 时间查询 db.logs.createIndex({ level: 1, created_at: -1 }) // TTL 索引(日志保留 30 天) db.logs.createIndex({ created_at: 1 }, { expireAfterSeconds: 30*24*3600 })

大表索引设计规范

  1. 索引要精简

    • 不要给低选择性字段(如 status=0/1)单独建索引。

    • 如果必须查询这种字段,最好和高选择性字段组合。

  2. 覆盖索引(Covered Index)

    • 查询只用到索引里的字段,MongoDB 可以直接返回结果,不用回表。

    • 例:

      db.logs.createIndex({ service: 1, created_at: -1 }) db.logs.find({ service: "user-api" }, { service: 1, created_at: 1, _id: 0 })

      👉 查询结果只用到索引里的字段 → 覆盖查询,速度更快。

  3. 分页优化

    • 大数据量下 skip 慢(需要扫描跳过前 N 行)。

    • 解决方案:用 范围查询 + limit 代替 skip

    • 例:

      db.logs.find({ service: "user-api", created_at: { $lt: lastTime } }) .sort({ created_at: -1 }) .limit(20)

🔹 4. 对比总结

类型特点使用场景注意事项
复合索引多字段组合索引,最左前缀规则用户+时间、文章+创建时间字段顺序很重要
多键索引数组字段自动展开建索引标签、分类、少量子数据数组过大性能差;不能同时用多个多键索引
大数据量表索引结合复合索引、TTL、覆盖索引日志、订单、监控数据避免低选择性索引;分页要优化

✅ 总结建议

  • 复合索引:遵循查询习惯 & 最左前缀原则

  • 多键索引:适合小数组字段,数组太大就拆表

  • 大数据量表:优先设计复合索引 + 覆盖索引,避免低选择性字段

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部