MongoDB

MongoDB 知识量:13 - 42 - 129

4.1 索引简介><

什么是索引- 4.1.1 -

索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。索引可以理解为一本书的目录,当需要查找一本书中的某一页内容时,可以先查找目录,找到相关的章节和页码,然后直接翻到对应的页码。在数据库中,索引就是一张包含了列名和对应数据位置的表格。当查询数据时,系统会先查找索引,然后根据索引指向的位置查找数据。

索引的创建可以提高数据库检索数据的速度,但会降低新增、修改、删除的效率,并且会浪费存储空间。因此,索引不是越多越好,需要根据实际情况添加不同的索引。常见的索引类型有单列索引和复合索引,适用场合也不同。单列索引适用于经常在where子句中引用某个列的情况,而复合索引适用于多个列的组合查询条件。

创建索引- 4.1.2 -

在MongoDB中,可以使用createIndex()方法来创建索引。以下是创建索引的基本语法:

db.collection.createIndex(keys, options)

其中,collection是要创建索引的集合名称,keys是一个包含要创建索引的字段名和排序方向的文档,options是一个可选参数,用于指定索引的选项。

下面是一个示例,演示如何在MongoDB中创建一个单字段索引:

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

这将在users集合上创建一个名为username_1的索引,该索引按username字段升序排序。

还可以使用createIndex()方法创建复合索引,如下所示:

db.users.createIndex({ firstName: 1, lastName: -1 })

这将在users集合上创建一个名为firstName_1_lastName_-1的复合索引,该索引首先按firstName字段升序排序,然后按lastName字段降序排序。

还可以使用options参数来指定索引的选项,例如唯一性约束、存储引擎等。以下是一个示例:

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

这将在users集合上创建一个唯一性约束的索引,确保username字段的值是唯一的。

创建索引后,可以使用getIndexes()方法来查看集合中的所有索引。例如:

db.users.getIndexes()

这将返回一个包含集合中所有索引的数组。

$运算符如何使用索引- 4.1.3 -

在MongoDB中,可以使用运算符与索引结合来优化查询性能。具体来说,当查询条件涉及到多个字段时,可以利用复合索引来提高查询效率。以下是一个使用运算符和索引的示例:

假设有一个名为"orders"的集合,包含订单信息,其中包含"customerId"、"orderDate"和"productId"等字段。为了优化查询性能,可以在这些字段上创建复合索引。

首先,创建一个复合索引:

db.orders.createIndex({ customerId: 1, orderDate: 1, productId: 1 })

这个索引按照customerId、orderDate和productId的顺序进行排序。

接下来,可以使用$运算符来构建查询条件,并利用索引进行优化。例如,如果想要查询特定customerId的所有订单,可以这样写:

db.orders.find({ customerId: '123' })

在这个查询中,MongoDB可以利用复合索引来快速定位到customerId为'123'的文档。

如果查询条件涉及到多个字段,也可以利用复合索引进行优化。例如,如果想要查询特定customerId在特定日期范围内购买的所有产品,可以这样写:

db.orders.find({ customerId: '123', orderDate: { $gte: new Date('2023-01-01'), $lt: new Date('2023-12-31') } })

在这个查询中,MongoDB会使用复合索引来查找满足条件的文档,从而提高查询效率。

索引文档和数组- 4.1.4 -

在MongoDB中,索引可以应用于文档的字段和数组字段。对于文档字段,索引可以加快查询速度,而数组字段上的索引可以加速数组中的元素查询。

当索引应用于文档字段时,MongoDB会创建一个索引,用于快速定位包含特定值的文档。例如,如果有一个名为users的集合,并且想要在name字段上创建一个索引,可以使用以下命令:

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

这将创建一个升序索引,用于加速基于name字段的查询。

当索引应用于数组字段时,MongoDB会创建一个索引,用于快速定位包含特定值的数组元素。例如,如果有一个名为orders的集合,并且想要在products数组字段上创建一个索引,可以使用以下命令:

db.orders.createIndex({ products: 1 })

这将创建一个升序索引,用于加速基于products数组字段的查询。通过索引数组,可以快速查询包含特定产品的订单。

explain输出- 4.1.5 -

在MongoDB中,explain()方法用于查看查询的执行计划,帮助开发者理解查询是如何执行的,以及如何优化查询性能。explain()方法可以返回查询的执行细节,包括扫描的文档数量、使用的索引、查询的扫描范围等。

explain()方法可以与不同的参数一起使用,以获取不同类型的执行计划信息。常见的参数包括:

  • executionStats:返回查询的执行统计信息,包括查询的总时间、扫描的文档数、使用的索引等。

  • allPlansExecution:返回所有可能的执行计划,包括未使用索引的计划。

  • queryPlanner:返回查询的查询规划器信息,包括查询的扫描范围、索引的使用情况等。

使用explain()方法的基本语法如下:

db.collection.find().explain(type)

其中,collection是要查询的集合名称,find()是查询条件,type是执行计划的类型(如executionStats、allPlansExecution、queryPlanner等)。

下面是一个示例,演示如何使用explain()方法查看查询的执行计划:

db.orders.find({ productId: '123' }).explain('executionStats')

上述示例中,使用explain('executionStats')来获取查询的执行统计信息,包括扫描的文档数、使用的索引等。通过查看这些信息,可以了解查询的性能瓶颈,并采取相应的优化措施。

何时不使用索引- 4.1.6 -

虽然索引可以提高查询性能,但并不是在所有情况下都应该使用索引。以下是一些不建议使用索引的情况:

  • 小表查询:对于非常小的表,全表扫描可能比使用索引更快。因为索引需要额外的存储空间和维护成本。

  • 低选择性查询:如果查询中的条件对于表中的大部分文档都为真,那么使用索引可能不会带来明显的性能提升。

  • 频繁更新的字段:如果一个字段经常被更新,那么维护索引的成本可能会很高,因为每次更新都需要更新索引。

  • 插入和删除操作:当插入或删除文档时,MongoDB需要更新索引。因此,对于有大量插入和删除操作的集合,使用索引可能会降低性能。

  • 大量重复值:如果字段中有大量重复值,那么该字段上的索引可能不会提供太大的性能提升。

  • 不经常查询的字段:如果一个字段很少被查询,那么为它创建索引可能不是很有意义。

  • 复合索引的次要字段:在复合索引中,如果查询条件只涉及到复合索引的第一个字段,那么该复合索引可能不会被有效使用。

  • 数据分布不均:如果数据在某个字段上分布不均,那么该字段上的索引可能不会提供最佳性能。

  • 全文搜索:对于全文搜索,MongoDB建议使用专门的文本索引而不是常规的B-tree索引。