Docs 菜单

Docs 主页开发应用程序MongoDB Manual

ESR(相等、排序、范围)规则

在此页面上

  • 相等
  • 排序
  • 范围
  • 其他注意事项
  • 例子
  • 进一步讨论

引用多个字段的索引为复合索引。复合索引可大幅缩短查询响应时间。

索引键与文档字段相对应。大多数情况下,应用 ESR(相等、排序、范围)规则来排列索引键有助于创建更有效的复合索引

本页介绍了 ESR 规则。有关优化查询的详细信息,请参阅 explain查询计划。

提示

要强制 MongoDB 使用特定索引,请在测试索引时使用 cursor.hint()

“相等”系指单个值的精确匹配。以下精确匹配查询扫描 cars 集合以查找 model 字段 Cordoba 精确匹配的文档。

db.cars.find( { model: "Cordoba" } )
db.cars.find( { model: { $eq: "Cordoba" } } )

索引搜索可有效利用精确匹配来限制完成查询时需要检查的文档数量。将需要精确匹配的字段放在索引中的前面。

一个索引可能有多个用于精确匹配的键。用于等值匹配的索引键可以以任何顺序出现。但是,如要使用索引满足等值匹配,所有用于精确匹配的索引键必须放在其他索引字段之前。MongoDB 的搜索算法让您无需以特定顺序排列精确匹配字段。

精确匹配应具有选择性,即只匹配少数文档。为了减少扫描的索引键数量,请在等值匹配的测试中确保判断条件能筛选掉至少 90% 的文档。

“排序”决定结果的顺序。排序操作在等值匹配之后,因为等值匹配会减少需要排序的文档数量。在等值匹配之后进行排序还能让 MongoDB 进行非阻塞排序。

当查询字段是索引键的子集时,索引可以支持排序操作。仅当查询包含排序键之前的所有前缀键的相等条件时,才支持对索引键子集进行排序操作。有关详细信息,请参阅索引的排序和非前缀子集。

以下示例将查询 cars 集合。输出将按 model 进行排序:

db.cars.find( { manufacturer: "GM" } ).sort( { model: 1 } )

要提高查询性能,请对 manufacturermodel 字段创建索引:

db.cars.createIndex( { manufacturer: 1, model: 1 } )
  • manufacturer 是第一个键,因为它是相等匹配。

  • model 按照与查询相同的顺序 (1) 建立索引。

“范围”筛选器扫描字段。扫描不需要精确匹配,这意味着范围筛选器与索引键松散绑定。为了提高查询效率,请限制范围边界并使用等值匹配来减少要扫描的文档数量。

范围筛选器类似如下内容:

db.cars.find( { price: { $gte: 15000} } )
db.cars.find( { age: { $lt: 10 } } )
db.cars.find( { priorAccidents: { $ne: null } } )

MongoDB 无法对范围筛选器的结果执行索引排序。将范围筛选器放在排序谓词之后,以便 MongoDB 可以使用非阻塞索引排序。有关阻塞排序的更多信息,请参阅cursor.allowDiskUse()

  • 不等式操作符,如 $ne$nin 是范围操作符,而不是相等操作符。

  • $regex 是个范围操作符。

  • $in

    • $in 单独使用时,它是一个执行一系列相等匹配的相等运算符。

    • $in.sort()一起使用时:

      • 如果$in的数组元素少于200 ,则元素将展开,然后按照为索引指定的排序顺序进行合并。这提高了小型数组的性能。 $in类似于具有 ESR 的相等谓词。

      • 如果$in具有200个或更多元素,则这些元素的排序方式类似于范围操作符。在这种情况下,无法实现小型阵列的性能改进。索引中的后续字段无法提供排序, $in类似于具有 ESR 的范围谓词。

      • 如果通常将$ins与小型数组一起使用,请在索引规范的前面部分包含$ins 。如果通常使用大型数组,请在要包含范围谓词的位置包含$ins

注意

200限制可能会发生变化,并且不能保证对于所有 MongoDB 版本都保持不变。

以下查询在 cars 集合中搜索福特制造的价格超过 15,000 美元的车辆。结果按车型排序:

db.cars.find(
{
manufacturer: 'Ford',
cost: { $gt: 15000 }
} ).sort( { model: 1 } )

该查询包含了 ESR 规则中的所有元素:

  • manufacturer: 'Ford' 为基于相等的匹配操作

  • cost: { $gt: 15000 } 为基于范围的匹配操作,并且

  • model 用于排序

根据 ESR 规则,对于该示例查询,最优的索引为:

{ manufacturer: 1, model: 1, cost: 1 }

许多 MongoDB 会议报告都深入讨论了 ESR 规则。

← 索引策略