MongoDB 高级索引
MongoDB 提供了强大的索引功能,以提高查询性能。除了基本的单字段索引和复合索引之外,MongoDB 还支持一系列高级索引类型,用于优化不同的查询场景。
1. 唯一索引(Unique Index)
唯一索引用于确保字段值的唯一性,类似于 SQL 的 UNIQUE 约束。
创建唯一索引
db.users.createIndex({ email: 1 }, { unique: true })
作用:
- 确保
email字段的值在集合中是唯一的。 - 如果插入重复值,MongoDB 将报错。
删除唯一索引
db.users.dropIndex("email_1")
2. 部分索引(Partial Index)
部分索引仅对符合特定条件的文档建立索引,减少索引大小,提高性能。
示例:仅索引 status 为 “active” 的用户
db.users.createIndex(
{ lastLogin: 1 },
{ partialFilterExpression: { status: "active" } }
)
作用:
- 仅对
status为"active"的文档创建索引,减少索引存储占用。 - 提高查询效率,适用于查询某些特定类型的文档。
3. 稀疏索引(Sparse Index)
稀疏索引只索引包含指定字段的文档,未包含该字段的文档不会被索引,从而节省存储空间。
示例:创建 phone 字段的稀疏索引
db.users.createIndex({ phone: 1 }, { sparse: true })
作用:
- 仅对
phone字段存在的文档建立索引,减少索引大小。 - 查询
phone的时候可以使用索引,但查询phone: null时不会走索引。
4. 复合索引(Compound Index)
复合索引用于多个字段的组合查询,优化复合条件查询的性能。
示例:创建 age 和 city 复合索引
db.users.createIndex({ age: 1, city: 1 })
作用:
- 可优化以下查询:
db.users.find({ age: 30, city: "New York" }) // 使用索引
db.users.find({ age: 30 }) // 使用索引
- 但 不会 优化:
db.users.find({ city: "New York" }) // 不能单独使用 city 字段索引
索引前缀原则:
db.users.find({ age: 30 })可以 使用索引(匹配索引的第一个字段)。db.users.find({ city: "New York" })不会 使用索引(必须包含age才能使用)。- 索引字段的顺序很重要,如果查询经常用
city作为首要查询条件,则应该创建{ city: 1, age: 1 }。
5. 文字索引(Text Index)
MongoDB 提供全文索引,用于高效地进行文本搜索。
示例:创建全文索引
db.articles.createIndex({ content: "text" })
查询示例:
db.articles.find({ $text: { $search: "MongoDB" } })
作用:
- 允许快速搜索包含 “MongoDB” 关键词的文档。
- 适用于文章、博客等场景。
6. 哈希索引(Hashed Index)
哈希索引用于优化基于 _id 或随机字段的查询。
示例:创建哈希索引
db.users.createIndex({ userId: "hashed" })
作用:
- 适用于等值查询,如
db.users.find({ userId: "abc123" })。 - 不能用于范围查询(
$gt、$lt等)。
7. 地理空间索引(Geospatial Index)
MongoDB 支持 2dsphere 和 2d 索引,用于处理地理坐标查询,如查找附近的商店、用户等。
示例:创建 2dsphere 索引
db.places.createIndex({ location: "2dsphere" })
查询附近的位置
db.places.find({
location: {
$near: {
$geometry: { type: "Point", coordinates: [40.7128, -74.0060] },
$maxDistance: 5000 // 5公里范围内
}
}
})
作用:
- 适用于 GPS 位置查询,如查找附近的餐馆、ATM、商店等。
8. TTL(Time-To-Live)索引
TTL 索引用于自动删除过期数据,常见于日志、临时数据存储等。
示例:创建 TTL 索引
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })
作用:
- 文档在
createdAt字段创建 1 小时(3600 秒)后自动删除。 - 适用于会话管理、缓存数据。
9. 覆盖索引(Covered Query)
如果一个查询的所有字段都在索引中,则称为覆盖查询,MongoDB 只需从索引中获取数据,无需访问磁盘中的文档,极大提高查询性能。
示例:创建复合索引
db.users.createIndex({ name: 1, age: 1 })
查询可以直接使用索引覆盖
db.users.find({ name: "Alice" }, { name: 1, age: 1, _id: 0 })
作用:
- 查询的
name和age都在索引中,且查询不包含额外字段,因此是覆盖查询,性能更优。
10. 多键索引(Multikey Index)
多键索引用于数组字段,使得查询数组中的元素更高效。
示例:数组字段索引
db.products.createIndex({ tags: 1 })
查询
db.products.find({ tags: "electronics" })
作用:
- 允许对数组中的每个元素建立索引,提高查询速度。
总结
| 索引类型 | 作用 | 适用场景 |
|---|---|---|
| 唯一索引 | 确保字段值唯一 | 唯一用户标识(email、username) |
| 部分索引 | 仅索引符合条件的文档 | 过滤特定条件的文档 |
| 稀疏索引 | 仅索引包含字段的文档 | 可选字段 |
| 复合索引 | 多字段查询优化 | 组合查询 |
| 文本索引 | 文本搜索 | 文章、博客、评论 |
| 哈希索引 | 快速等值查询 | _id、唯一标识字段 |
| 地理索引 | 位置查询 | 查找附近地点 |
| TTL 索引 | 自动删除过期数据 | 会话、日志 |
| 覆盖索引 | 查询仅使用索引 | 提高查询性能 |
| 多键索引 | 数组字段索引 | 标签、分类、兴趣标签 |
更多详细内容请关注其他相关文章!