MongoDB索引单字段复合索引

wen java案例 3

本文目录导读:

MongoDB索引单字段复合索引

  1. 单字段索引
  2. 复合索引
  3. 复合索引的关键规则
  4. 实际应用示例
  5. 最佳实践
  6. 性能考虑
  7. 常见问题

我来详细解释MongoDB中的单字段索引和复合索引。

单字段索引

基本概念

单字段索引是最简单的索引类型,只在一个字段上建立索引。

创建语法

// 升序索引
db.collection.createIndex({ fieldName: 1 })
// 降序索引
db.collection.createIndex({ fieldName: -1 })
// 唯一索引
db.collection.createIndex({ fieldName: 1 }, { unique: true })

示例

// 创建单字段索引
db.users.createIndex({ email: 1 })
// 创建唯一索引
db.users.createIndex({ username: 1 }, { unique: true })
// 创建降序索引(适用于日期排序)
db.orders.createIndex({ createdAt: -1 })

适用场景

  • 精确匹配查询
  • 范围查询
  • 排序操作

复合索引

基本概念

复合索引在多个字段上建立索引,字段的顺序很重要。

创建语法

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

示例

// 查询用户按年龄和名字排序
db.users.createIndex({ age: 1, name: 1 })
// 订单按用户和日期查询
db.orders.createIndex({ userId: 1, createdAt: -1 })

复合索引的关键规则

最左前缀原则

复合索引支持所有前缀的查询:

// 创建索引: { a: 1, b: 1, c: 1 }
// 支持的查询
{ a: 1 }                    // 使用索引
{ a: 1, b: 2 }             // 使用索引
{ a: 1, b: 2, c: 3 }      // 使用索引
// 不支持的查询
{ b: 1 }                    // 不使用索引
{ c: 1 }                    // 不使用索引
{ b: 1, c: 1 }             // 不使用索引

排序规则

复合索引的字段顺序影响排序操作:

// 索引: { age: 1, name: -1 }
// 支持的排序
db.users.find().sort({ age: 1, name: -1 })   // 使用索引
db.users.find().sort({ age: 1 })              // 使用索引
db.users.find().sort({ age: -1, name: 1 })    // 使用索引(反向)
// 不支持的排序
db.users.find().sort({ name: -1 })            // 不使用索引
db.users.find().sort({ age: -1, name: -1 })   // 不使用索引

实际应用示例

电商系统订单查询

// 需求:按用户查询订单,并按时间倒序排列
db.orders.createIndex({ userId: 1, createdAt: -1 })
// 高效查询
db.orders.find({ userId: "user123" }).sort({ createdAt: -1 })
db.orders.find({ 
  userId: "user123", 
  createdAt: { $gte: ISODate("2024-01-01") } 
}).sort({ createdAt: -1 })

社交媒体帖子搜索

// 需求:查询某个用户的帖子,按时间排序
db.posts.createIndex({ author: 1, timestamp: -1 })
// 覆盖查询
db.posts.find({ 
  author: "user456",
  timestamp: { $gt: ISODate("2024-06-01") }
}).sort({ timestamp: -1 })

最佳实践

索引设计原则

// ❌ 不好的设计
db.collection.createIndex({ field1: 1 })
db.collection.createIndex({ field1: 1, field2: 1 })
// ✅ 好的设计(复合索引包含单字段索引的功能)
db.collection.createIndex({ field1: 1, field2: 1 })

查询选择性

// 选择性高的字段放在前面
db.users.createIndex({ 
  email: 1,    // 高选择性(唯一)
  status: 1    // 低选择性(只有几个值)
})

使用分析工具

// 查看查询是否使用索引
db.collection.find({ ... }).explain("executionStats")
// 查看集合索引
db.collection.getIndexes()

性能考虑

索引对写入的影响

  • 每个索引都会增加写入操作的负担
  • 复合索引通常比多个单字段索引更高效

内存使用

// 查看索引大小
db.collection.totalIndexSize()
// 限制索引数量(建议不超过5个)

索引覆盖查询

// 查询的字段都在索引中
db.collection.createIndex({ name: 1, age: 1 })
db.collection.find(
  { name: "张三" }, 
  { _id: 0, name: 1, age: 1 }
)
// 这样查询只从索引中获取数据,不访问文档

常见问题

索引选择错误

// 使用hint()强制使用特定索引
db.collection.find({ ... }).hint({ field1: 1, field2: -1 })

索引失效的场景

  • 使用$ne, $nin, $not操作符
  • 在索引字段上使用函数
  • 正则表达式(非前缀匹配)

合理使用单字段和复合索引,可以大幅提升MongoDB的查询性能,建议根据实际查询模式进行索引设计,避免过度索引。

抱歉,评论功能暂时关闭!