22.MongoDB单字段索引

22.MongoDB单字段索引


22.1 知识点

单字段索引

MongoDB 的单字段索引操作是指对集合中的某一个字段创建索引,以加速基于该字段的查询操作。单字段索引是最常见和基础的索引类型,适用于大多数情况,尤其是在查询条件中频繁使用该字段时。

语法

db.collection.createIndex({ fieldName: 1 })
  • **{ fieldName: 1 }**:表示按照升序索引(1 为升序,-1 为降序)。
  • 通常,升序索引和降序索引的查询效果是相同的。
  • 但有些特殊场景(如排序)会影响选择哪种顺序。

假设有一个 users 集合,包含 nameage 字段,以下命令会为 name 字段创建升序索引:

// 默认索引名字
db.users.createIndex({ name: 1 })
// 自定义索引名字
db.users.createIndex({ name: 1 }, { name: "custom_name_index" })

查询时使用索引

一旦为字段创建了索引,查询操作会自动利用索引加速。例如:

db.users.find({ name: "张三" })

检查索引

使用 getIndexes() 可以查看集合中现有的索引:

db.users.getIndexes()

这会返回一个数组,列出所有索引的信息,包括单字段索引和复合索引。

结果:

[ { v: 2, key: { _id: 1 }, name: '_id_' } ]

结果参数

v: 2

这个字段表示索引的版本。MongoDB 从 v1 开始就支持索引,并且在后续版本中对索引格式进行过更新。索引版本号 (v) 主要用来表示当前数据库所使用的索引格式。在你的查询结果中,v: 2 表示这是一个版本为 2 的索引格式。

  • v: 1:表示旧版本的索引格式(MongoDB 2.x 及更早版本使用)。
  • v: 2:表示现代的索引格式,适用于 MongoDB 3.x 及以上版本。
key: { _id: 1 }

key 字段描述了索引的字段和排序方式。在这个例子中,索引是基于 _id 字段的。具体来说:

  • _id 是 MongoDB 默认的主键字段,每个文档都拥有一个唯一的 _id 值。
  • 1 表示按照升序进行排序。

所以,这个索引表示在 _id 字段上创建了一个升序索引。实际上,这个索引是 MongoDB 默认创建的主键索引,确保每个文档的 _id 字段唯一且有序。

name: id

name 字段表示索引的名称。在这个例子中,索引的名称是 _id_,这是默认的主键索引名称。在 MongoDB 中,每个集合都会自动为 _id 字段创建一个名为 _id_ 的唯一索引。

  • 如果你没有为某个字段显式创建索引,MongoDB 会为 _id 字段自动创建这个索引。
  • name: '_id_' 表示这是该集合中 _id 字段的索引,名称是由 MongoDB 自动生成的。

删除索引

如果某个索引不再需要,可以使用 dropIndex() 删除:

db.users.dropIndex("name_1")

其中,name_1 是索引的名称,通常由字段名和索引顺序(升序或降序)组成。

示例

在这种情况下,MongoDB 会使用 name 字段的索引来加速查询过程,而不是全表扫描。

age 字段创建单字段索引

db.users.createIndex({ age: 1 })

查询特定年龄的用户,索引会加速查询

db.users.find({ age: { $gt: 25 } })

email 字段创建降序索引

db.users.createIndex({ email: -1 })

覆盖索引

覆盖索引(Covering Index)是一种特殊的索引优化方式。当查询的字段被索引,并且查询结果只包含索引中的字段时,MongoDB 会直接使用该索引返回查询结果,而无需访问原始文档。这种方式可以显著提高查询效率,特别是在查询只需要少量字段的情况下。

如何工作

如果查询的字段已经创建了索引,而且查询结果只需要这些索引中的字段(例如,查询字段 name,返回的也是 name),MongoDB 会利用覆盖索引来执行查询,而不是读取整个文档。这意味着,MongoDB 只需要扫描索引,而不需要从磁盘加载整个文档内容,从而减少了 I/O 操作。

示例

假设 users 集合中有一个索引是基于 name 字段的:

db.users.createIndex({ name: 1 })

接着,你执行以下查询:

// 在 users 集合中查找 name 字段为 "John" 的文档,并且只返回这些文档中的 name 字段。
// { name: 1 } 表示只返回查询结果中的 name 字段。
db.users.find({ name: "John" }, { name: 1 })

由于查询只涉及 name 字段,并且 name 字段有索引,MongoDB 可以直接使用索引来返回结果,而不需要读取整个文档。这是因为索引中已经包含了查询所需的所有字段。

优势

  • 减少 I/O 操作:只需要读取索引,而无需加载完整的文档。
  • 提高查询速度:索引结构通常更小且访问速度更快。
  • 节省内存:直接从索引获取结果,不需要加载大量不相关的字段。

注意事项

覆盖索引只适用于那些查询的字段和返回的字段完全包含在索引中的情况。如果查询请求的字段不完全包含在索引中,MongoDB 仍然需要访问原始文档。

注意事项

  1. 同一个字段有不同的查询条件(升序/降序)
  2. 不同的查询涉及多个字段时,索引的选择变得复杂

MongoDB 的单字段索引只能指定升序(1)或降序(-1)其中之一。如果你想同时满足升序和降序的查询要求,可以考虑 复合索引 等来进行操作。



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏