MongoDB索引类型详解与管理指南

2 阅读3分钟

MongoDB索引:核心类型与管理实战

MongoDB索引为用户提供了一种高效查询数据的方式。在没有索引的情况下查询数据,查询将不得不搜索数据库中的所有记录以找到匹配查询的数据。在MongoDB中,没有索引的查询称为集合扫描。集合扫描会导致各种性能瓶颈,并显著减慢应用程序速度。

幸运的是,使用MongoDB索引可以解决这两个问题。通过限制需要查询的文档数量,可以提高应用程序的整体性能。

MongoDB索引是什么?

MongoDB索引是特殊的数据结构,它使得查询数据库更快。它们通过以高效的方式存储数据集的一小部分来加速查找和检索数据——您无需扫描数据集合中的每个文档。MongoDB索引将索引字段的值存储在数据集合之外,并跟踪它们在磁盘上的位置。索引字段按值排序,这使得执行相等匹配和高效地进行基于范围的查询变得容易。

您可以在集合级别定义MongoDB索引,因为支持对集合中任何字段或子字段的索引。您可以使用Atlas CLI或Atlas UI来管理数据集合上的索引。两者都使查询执行更高效。

为什么MongoDB需要索引?

索引在MongoDB中是无价的。它们是组织集合中信息的有效方式,可以加速查询,更快地返回相关结果。通过使用索引来分组、排序和检索数据,您可以节省大量时间。您的数据库引擎不再需要筛选每条记录来查找匹配项。

索引的缺点是什么?

索引确实有一些缺点。您创建的每个索引都会影响写入性能,并且每个索引都会占用磁盘空间。为了避免集合膨胀和写入变慢,请仅创建真正必要的索引。

可以使用多少个索引?

MongoDB索引每个数据集合上限为64个。在复合索引中,最多只能有32个字段。$text查询需要特殊的文本索引——您不能将其与需要不同类型特殊索引的另一个查询操作符结合使用。

索引实战

在本教程中,我们将使用以下数据集来演示MongoDB的索引功能:

use students
db.createCollection("studentgrades")
db.studentgrades.insertMany(
    [
        {name: "Barry", subject: "Maths", score: 92},
        {name: "Kent", subject: "Physics", score: 87},
        {name: "Harry", subject: "Maths", score: 99, notes: "Exceptional Performance"},
        {name: "Alex", subject: "Literature", score: 78},
        {name: "Tom", subject: "History", score: 65, notes: "Adequate"}
    ]
)
db.studentgrades.find({},{_id:0})

MongoDB索引是唯一的吗?

在集合中创建文档时,MongoDB使用_id字段创建唯一索引。MongoDB将此称为默认_id索引。此默认索引不能从集合中删除。

如何在MongoDB中创建索引

要在MongoDB中创建索引,请使用createIndex()方法,语法如下:

db.<collection>.createIndex(<Key and Index Type>, <Options>)

创建索引时,定义要索引的字段和键的方向(1或-1)以指示升序或降序。如果使用降序单字段索引,可能会降低性能。如果您想要最佳结果,最好使用升序单字段索引。

另一件需要注意的事情是索引名称。默认情况下,MongoDB会通过使用下划线作为分隔符,将索引键与索引中每个键的方向连接来生成索引名称。例如:{name: 1}将被创建为name_1。最佳实践是在创建索引时使用name选项定义自定义索引名称。索引创建后无法重命名。重命名索引的唯一方法是先删除该索引(如下所示),然后使用所需名称重新创建。

createIndex() 示例

让我们在studentgrades集合中使用name字段创建一个索引,并将其命名为student name index

db.studentgrades.createIndex(
{name: 1},
{name: "student name index"}
)

在MongoDB中查找索引

您可以使用getIndexes()方法查找MongoDB集合中所有可用的索引。这将返回特定集合中的所有索引。

db.<collection>.getIndexes()

getIndexes() 示例

让我们使用以下命令查看studentgrades集合中的所有索引:

db.studentgrades.getIndexes()

输出包含默认的_id索引和用户创建的索引student name index

如何在MongoDB中列出索引

您可以使用Shell或Compass列出数据集合上的索引。此命令将为您提供一个索引文档数组:

db.collection.getIndexes()

另一种方法是使用MongoDB Atlas UI。打开一个集群并转到“集合”选项卡。选择数据库和集合,然后单击“索引”以查看列出的索引。最后,您可以在MongoDB Atlas CLI中使用以下命令查看索引:

atlas clusters index list --clusterName <your-cluster> --db <database> --collection <collection>

如何在MongoDB中删除索引

要从MongoDB集合中删除索引,请使用dropIndex()方法,同时指定要删除的索引名称。

db.<collection>.dropIndex(<Index Name / Field Name>)

dropIndex() 示例

让我们删除索引名为student name index的用户创建索引,如下所示。

db.studentgrades.dropIndex("student name index")

您也可以使用索引字段值来删除没有定义名称的索引:

db.studentgrades.dropIndex({name:1})

dropIndexes命令还可以删除除默认_id索引之外的所有索引。

db.studentgrades.dropIndexes()

MongoDB中有哪些不同类型的索引?

MongoDB提供了可以根据用户需求使用的不同类型的索引。以下是MongoDB中的主要索引类型:

  • 单字段索引
  • 复合索引
  • 多键索引

除了上面提到的主要索引类型外,MongoDB还提供了一些针对特定用例的特殊索引类型:

  • 地理空间索引
  • 文本索引
  • 哈希索引

单字段索引

这些用户定义的索引使用文档中的单个字段按升序或降序(1或-1)创建索引。在单字段索引中,索引键的排序顺序没有影响,因为MongoDB可以沿任一方向遍历索引。

示例
db.studentgrades.createIndex({name: 1})

上面的索引将使用name字段按升序对数据进行排序。您可以使用sort()方法查看数据在索引中的表示方式。

db.studentgrades.find({},{_id:0}).sort({name:1})

复合索引

您可以使用MongoDB文档中的多个字段来创建复合索引。这种类型的索引将使用第一个字段进行初始排序,然后按前面的字段排序。

示例

在下面的复合索引中,MongoDB将:

  • 首先按subject字段排序
  • 然后,在每个subject值内,按score排序
db.studentgrades.createIndex({subject: 1, score: -1})

该索引将创建类似于以下内容的数据结构:

db.studentgrades.find({},{_id:0}).sort({subject:1, score:-1})

多键索引

MongoDB支持索引数组字段。当您为包含数组的字段创建索引时,MongoDB将为数组中的每个元素创建单独的索引条目。这些多键索引使用户能够使用数组中的元素查询文档。当遇到数组字段时,MongoDB会自动创建多键索引,无需用户显式定义多键类型。

示例

让我们创建一个包含数组字段的新数据集来演示MongoDB中多键索引的创建。

db.createCollection("studentperformance")
db.studentperformance.insertMany(
[
{name: "Barry", school: "ABC Academy", grades: [85, 75, 90, 99] },
{name: "Kent", school: "FX High School", grades: [74, 66, 45, 67]},
{name: "Alex", school: "XYZ High", grades: [80, 78, 71, 89]},
]
)
db.studentperformance.find({},{_id:0}).pretty()

现在让我们使用grades字段创建一个索引。

db.studentperformance.createIndex({grades:1})

上面的代码将自动在MongoDB中创建一个多键索引。当您使用数组字段(grades)查询文档时,MongoDB将搜索find()方法中定义的数组的第一个元素,然后搜索整个匹配的查询。

地理空间索引

MongoDB提供两种类型的索引来提高处理地理空间坐标数据时的数据库查询效率:

  • 2d索引:使用平面几何,适用于MongoDB 2.2及更早版本中使用的传统坐标对。
  • 2dsphere索引:使用球面几何。

语法:

db.<collection>.createIndex( { <location Field> : "2dsphere" } )

文本索引

文本索引类型使您能够搜索集合中的字符串内容。

语法:

db.<collection>.createIndex( { <Index Field>: "text" } )

哈希索引

MongoDB哈希索引类型用于提供对基于哈希的分片功能的支持。这将索引指定字段的哈希值。

语法:

db.<collection>.createIndex( { <Index Field> : "hashed" } )

MongoDB索引属性

您可以通过使用索引属性来进一步增强索引的功能。在本节中,您将了解这些常用的索引属性:

  • 稀疏索引属性
  • 部分索引属性
  • 唯一索引属性

稀疏索引属性

MongoDB稀疏属性允许索引在索引字段在文档中不可用时省略对集合中文档的索引,并创建一个仅包含索引字段的文档的索引。

示例
db.studentgrades.createIndex({notes:1},{sparse: true})

在之前的studentgrades集合中,如果使用notes字段创建索引,它将只索引两个文档,因为notes字段只存在于两个文档中。

部分索引属性

部分索引功能允许用户创建匹配特定过滤条件的索引。部分索引使用partialFilterExpression选项来指定过滤条件。

示例
db.studentgrades.createIndex(
{name:1},
{partialFilterExpression: {score: { $gte: 90}}}
)

上面的代码将为name字段创建一个索引,但仅包含score字段值大于或等于90的文档。

唯一索引属性

唯一属性使用户能够创建一个仅包含唯一值的MongoDB索引。这将:

  • 拒绝索引字段中的任何重复值
  • 将索引限制为包含唯一值的文档
示例
db.studentgrades.createIndex({name:1},{unique: true})

上面创建的索引将把索引限制为name字段具有唯一值的文档。

索引回顾

本MongoDB索引教程和指南到此结束。您学习了如何创建、查找和删除索引,使用不同的索引类型,以及创建复杂的索引。然后,可以使用这些索引进一步增强MongoDB数据库的功能,提高利用快速数据库查询的应用程序的性能。FINISHED