创建 MongoDB 索引

MongoDBMongoDBBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本实验中,你将学习在 MongoDB 中创建索引的基本概念和技术。实验涵盖以下步骤:创建单字段索引、构建复合索引、设置唯一索引、检查索引使用情况以及查看索引列表。这些索引技术可以通过优化数据检索显著提高 MongoDB 查询的性能。实验提供了动手示例和逐步指导,帮助你有效理解和应用这些索引概念。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL mongodb(("MongoDB")) -.-> mongodb/ErrorHandlingGroup(["Error Handling"]) mongodb(("MongoDB")) -.-> mongodb/BasicOperationsGroup(["Basic Operations"]) mongodb(("MongoDB")) -.-> mongodb/QueryOperationsGroup(["Query Operations"]) mongodb(("MongoDB")) -.-> mongodb/IndexingGroup(["Indexing"]) mongodb/BasicOperationsGroup -.-> mongodb/start_mongodb_shell("Start MongoDB Shell") mongodb/BasicOperationsGroup -.-> mongodb/insert_document("Insert Document") mongodb/BasicOperationsGroup -.-> mongodb/delete_document("Delete Document") mongodb/QueryOperationsGroup -.-> mongodb/find_documents("Find Documents") mongodb/QueryOperationsGroup -.-> mongodb/query_with_conditions("Query with Conditions") mongodb/IndexingGroup -.-> mongodb/create_index("Create Index") mongodb/IndexingGroup -.-> mongodb/build_compound_index("Build Compound Index") mongodb/ErrorHandlingGroup -.-> mongodb/handle_write_errors("Handle Write Errors") subgraph Lab Skills mongodb/start_mongodb_shell -.-> lab-422078{{"创建 MongoDB 索引"}} mongodb/insert_document -.-> lab-422078{{"创建 MongoDB 索引"}} mongodb/delete_document -.-> lab-422078{{"创建 MongoDB 索引"}} mongodb/find_documents -.-> lab-422078{{"创建 MongoDB 索引"}} mongodb/query_with_conditions -.-> lab-422078{{"创建 MongoDB 索引"}} mongodb/create_index -.-> lab-422078{{"创建 MongoDB 索引"}} mongodb/build_compound_index -.-> lab-422078{{"创建 MongoDB 索引"}} mongodb/handle_write_errors -.-> lab-422078{{"创建 MongoDB 索引"}} end

创建单字段索引

在这一步中,你将学习如何在 MongoDB 中创建单字段索引,这可以通过加快数据检索速度显著提升查询性能。

首先,让我们启动 MongoDB shell 并准备环境:

mongosh

进入 MongoDB shell 后,创建一个数据库和一个包含示例数据的集合:

use indexlab
db.users.insertMany([
    { name: "Alice", age: 28, email: "[email protected]" },
    { name: "Bob", age: 35, email: "[email protected]" },
    { name: "Charlie", age: 42, email: "[email protected]" }
])

接下来,在 "age" 字段上创建一个单字段索引:

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

1 表示升序索引。如果你想要降序索引,可以使用 -1

为了验证索引是否创建成功,可以使用以下命令:

db.users.getIndexes();

示例输出:

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

让我们通过运行带索引和不带索引的查询来检查性能提升:

db.users.find({ age: 35 }).explain("executionStats");

explain() 方法将显示查询执行的详细信息,包括是否使用了索引。

构建复合索引

在这一步中,你将学习如何在 MongoDB 中创建复合索引,这种索引允许对多个字段进行索引,以优化复杂查询的性能。

让我们继续使用上一步中的数据库和集合:

use indexlab

复合索引是对多个字段的索引。我们将创建一个结合 "name" 和 "age" 字段的索引,以提升涉及这两个字段的查询性能:

db.users.createIndex({ name: 1, age: 1 });

这将创建一个索引,其中文档首先按名称升序排序,然后按年龄升序排序。

让我们添加更多文档来演示复合索引的效果:

db.users.insertMany([
  { name: "David", age: 28, email: "[email protected]" },
  { name: "Eve", age: 28, email: "[email protected]" },
  { name: "Frank", age: 35, email: "[email protected]" }
]);

现在,让我们验证复合索引:

db.users.getIndexes();

示例输出:

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

让我们运行一个可以从这个复合索引中受益的查询:

db.users.find({ name: "David", age: 28 }).explain("executionStats");

这个查询将使用我们刚刚创建的复合索引,从而显著提升查询性能。

设置唯一索引

在这一步中,你将学习如何在 MongoDB 中创建唯一索引,这种索引可以防止特定字段或字段组合中出现重复值。

让我们继续使用现有的数据库:

use indexlab

唯一索引确保索引字段的值在集合中是唯一的。我们将在 "email" 字段上创建一个唯一索引,以防止重复的电子邮件地址:

db.users.createIndex({ email: 1 }, { unique: true });

现在,让我们尝试插入具有重复电子邮件地址的文档:

// 这将成功
db.users.insertOne({
  name: "Grace",
  age: 29,
  email: "[email protected]"
});

// 这将因唯一索引而失败
try {
  db.users.insertOne({
    name: "Henry",
    age: 30,
    email: "[email protected]"
  });
} catch (e) {
  print("Duplicate email error:", e.message);
}

让我们验证唯一索引:

db.users.getIndexes();

示例输出:

[
  { v: 2, key: { _id: 1 }, name: '_id_' },
  { v: 2, key: { age: 1 }, name: 'age_1' },
  { v: 2, key: { name: 1, age: 1 }, name: 'name_1_age_1' },
  { v: 2, key: { email: 1 }, name: 'email_1', unique: true }
]

你也可以在多个字段上创建唯一索引。这意味着这些字段的组合必须是唯一的:

db.users.createIndex({ name: 1, age: 1 }, { unique: true });

这允许不同的用户拥有相同的名称或相同的年龄,但不能拥有完全相同的名称和年龄组合。

检查索引使用情况

在这一步中,你将学习如何使用 explain() 方法分析和理解 MongoDB 中的索引使用情况,以优化查询性能。

让我们继续使用现有的数据库:

use indexlab

首先,让我们运行一个未指定索引的查询并检查其性能:

db.users.find({ name: "Alice", age: 28 }).explain("executionStats");

在输出中需要关注的关键点:

  • winningPlan.stage:查找 "COLLSCAN"(集合扫描),这意味着它正在扫描所有文档
  • totalDocsExamined:扫描的文档数量
  • executionTimeMillis:查询执行所花费的时间

现在,让我们运行一个使用之前创建的复合索引的查询:

db.users
  .find({ name: "Alice", age: 28 })
  .hint({ name: 1, age: 1 })
  .explain("executionStats");

.hint() 方法强制 MongoDB 使用特定的索引。将此输出与之前的输出进行比较:

  • winningPlan.stage 现在应该显示 "FETCH" 和 "IXSCAN"
  • totalDocsExamined 应该会大幅减少
  • executionTimeMillis 应该显著降低

让我们创建一个更复杂的查询来演示索引的使用:

db.users.createIndex({ email: 1, age: 1 });

db.users
  .find({
    email: { $gt: "[email protected]" },
    age: { $gte: 30 }
  })
  .explain("executionStats");

此查询在 email 和 age 字段上使用了范围条件,这可以从复合索引中受益。

示例输出将显示:

  • 索引的使用方式
  • 性能改进
  • 详细的查询执行统计信息

查看索引列表

在这最后一步中,你将学习如何查看和管理 MongoDB 数据库中的索引列表,这对于理解和优化数据库性能至关重要。

让我们继续使用现有的数据库:

use indexlab

要查看当前数据库中的所有索引,可以使用 getIndexes() 方法:

db.users.getIndexes();

示例输出如下:

[
  { v: 2, key: { _id: 1 }, name: '_id_' },
  { v: 2, key: { age: 1 }, name: 'age_1' },
  { v: 2, key: { name: 1, age: 1 }, name: 'name_1_age_1' },
  { v: 2, key: { email: 1 }, name: 'email_1', unique: true },
  { v: 2, key: { email: 1, age: 1 }, name: 'email_1_age_1' }
]

让我们获取有关索引的更详细信息:

db.users.getIndexes().forEach(function (index) {
  print("Index Name: " + index.name);
  print("Index Key: " + JSON.stringify(index.key));
  print("Unique: " + (index.unique ? "Yes" : "No"));
  print("---");
});

要删除索引,可以使用 dropIndex() 方法。让我们删除 email 字段上的索引:

db.users.dropIndex("email_1");

验证索引是否已被删除:

db.users.getIndexes();

你也可以一次性删除多个索引:

// 删除多个特定索引
db.users.dropIndexes(["name_1_age_1", "email_1_age_1"]);

要删除所有用户创建的索引(保留默认的 _id 索引):

db.users.dropIndexes();

总结

在本实验中,你学习了如何在 MongoDB 中创建单字段索引,以通过更快的数据检索来提高查询性能。你还探索了构建复合索引,这种索引可以通过对多个字段进行索引来优化复杂查询。此外,你学习了如何设置唯一索引以确保数据的唯一性,检查索引使用情况,以及查看集合的索引列表。

本实验的关键要点包括理解索引的重要性、不同类型的索引(单字段索引和复合索引),以及如何在 MongoDB 数据库中管理和监控索引。这些技术可以显著提高 MongoDB 应用程序的效率和性能。