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