The ESR (Equality, Sort, Range) RuleESR(相等、排序、范围)规则
On this page本页内容
An index that references multiple fields is a compound index. 引用多个字段的索引是复合索引。Compound indexes can dramatically improve query response times.复合索引可以显著缩短查询响应时间。
Index keys correspond to document fields. 索引键对应于文档字段。In most cases, applying the ESR (Equality, Sort, Range) Rule to arrange the index keys helps to create a more efficient compound index.在大多数情况下,应用ESR(相等、排序、范围)规则来排列索引键有助于创建更高效的复合索引。
This page introduces the ESR Rule. 本页介绍ESR规则。For more information on tuning queries, see 有关优化查询的更多信息,请参阅explain
and Query Plans.explain
和查询计划。
To force MongoDB to use a particular index, use cursor.hint() when testing indexes.要强制MongoDB使用特定的索引,请在测试索引时使用cursor.hint()。
Equality相等
"Equality" refers to an exact match on a single value. “相等”指的是与单个值完全匹配。The following exact match queries scan the 以下精确匹配查询扫描cars
collection for documents whose model
field exactly matches Cordoba
.cars
集合,查找其model
字段与Cordoba
完全匹配的文档。
db.cars.find( { model: "Cordoba" } )
db.cars.find( { model: { $eq: "Cordoba" } } )
Index searches make efficient use of exact matches to limit the number of documents that need to be examined to satisfy a query. 索引搜索有效地利用精确匹配来限制需要检查以满足查询的文档数量。Place fields that require exact matches first in your index.将需要完全匹配的字段放在索引的第一位。
An index may have multiple keys for queries with exact matches. The index keys for equality matches can appear in any order. 对于具有完全匹配的查询,索引可能具有多个键。相等匹配的索引键可以按任何顺序显示。However, to satisfy an equality match with the index, all of the index keys for exact matches must come before any other index fields. 但是,为了满足与索引的相等匹配,用于精确匹配的所有索引键必须位于任何其他索引字段之前。MongoDB's search algorithm eliminates any need to arrange the exact match fields in a particular order.MongoDB的搜索算法消除了按特定顺序排列精确匹配字段的需要。
Exact matches should be selective. To reduce the number of index keys scanned, ensure equality tests eliminate at least 90% of possible document matches.精确匹配应该是选择性的。要减少扫描的索引键数量,请确保相等性测试至少消除90%可能的文档匹配。
Sort排序
"Sort" determines the order for results. Sort follows equality matches because the equality matches reduce the number of documents that need to be sorted. “排序”决定结果的顺序。排序遵循相等匹配,因为相等匹配减少了需要排序的文档数量。Sorting after the equality matches also allows MongoDB to do a non-blocking sort.相等匹配后的排序也允许MongoDB进行非阻塞排序。
An index can support sort operations when the query fields are a subset of the index keys. 当查询字段是索引键的子集时,索引可以支持排序操作。Sort operations on a subset of the index keys are only supported if the query includes equality conditions for all of the prefix keys that precede the sort keys. 只有当查询包括排序键之前的所有前缀键的相等条件时,才支持对索引键子集进行排序操作。For more information see:
Sort and Non-prefix Subset of an Index.有关详细信息,请参阅:索引的排序和非前缀子集。
The following example queries the 以下示例查询cars
collection. The output is sorted by model
:cars
集合。输出按model
排序:
db.cars.find( { manufacturer: "GM" } ).sort( { model: 1 } )
To improve query performance, create an index on the 要提高查询性能,请在manufacturer
and model
fields:manufacturer
字段和model
字段上创建索引:
db.cars.createIndex( { manufacturer: 1, model: 1 } )
manufacturer
is the first key because it is an equality match.是第一个键,因为它是相等匹配。model
is indexed in the same order (按与查询相同的顺序(1
) as the query.1
)进行索引。
Range范围
"Range" filters scan fields. “范围”筛选器扫描字段。The scan doesn't require an exact match, which means range filters are loosely bound to index keys. 扫描不需要完全匹配,这意味着范围筛选器与索引键松散绑定。To improve query efficiency, make the range bounds as tight as possible and use equality matches to limit the number of documents that must be scanned.为了提高查询效率,请尽可能缩小范围界限,并使用相等匹配来限制必须扫描的文档数量。
Range filters resemble the following:范围筛选器类似于以下内容:
db.cars.find( { price: { $gte: 15000} } )
db.cars.find( { age: { $lt: 10 } } )
db.cars.find( { priorAccidents: { $ne: null } } )
MongoDB cannot do an index sort on the results of a range filter. MongoDB不能对范围筛选器的结果进行索引排序。Place the range filter after the sort predicate so MongoDB can use a non-blocking index sort. 将范围筛选器放在排序谓词之后,以便MongoDB可以使用非阻塞索引排序。For more information on blocking sorts, see 有关阻塞排序的更多信息,请参阅cursor.allowDiskUse()
.cursor.allowDiskUse()
。
Additional Considerations其他注意事项
Inequality operators such as $ne
or $nin
are range operators, not equality operators.$ne
或$nin
等不等式运算符是范围运算符,而不是等式运算符。
$regex
is a range operator.
$in
can be an equality operator or a range operator. 可以是相等运算符或范围运算符。When 单独使用$in
is used alone, it is an equality operator that does a series of equality matches. $in
时,它是一个进行一系列相等匹配的相等运算符。$in
acts like a range operator when it is used with .sort()
.$in
与.sort()
一起使用时,其作用类似于范围运算符。
Example实例
The following query searches the 以下查询在cars
collection for vehicles manufactured by Ford that cost more than $15,000 dollars. cars
集合中搜索福特制造的售价超过15000美元的汽车。The results are sorted by model:结果按模型排序:
db.cars.find(
{
manufacturer: 'Ford',
cost: { $gt: 15000 }
} ).sort( { model: 1 } )
The query contains all the elements of the ESR Rule:该查询包含ESR规则的所有元素:
manufacturer: 'Ford'
is an equality based match是基于相等的匹配cost: { $gt: 15000 }
is a range based match, and是基于范围的匹配,并且model
is used for sorting用于排序
Following the ESR rule, the optimal index for the example query is:根据ESR规则,示例查询的最佳索引为:
{ manufacturer: 1, model: 1, cost: 1 }
Further Discussion进一步讨论
A number of MongoDB conference presentations discuss the ESR rule in depth.许多MongoDB会议演示深入讨论了ESR规则。