查询优化


进入MongoDB中文手册(4.2版本)目录

索引通过减少查询操作需要处理的数据量来提高读取操作的效率。这简化了与在MongoDB中实现查询相关的工作。

1 创建索引来支持读操作

如果您的应用程序查询特定字段或一组字段上的集合,则查询字段上的索引或该字段集上的复合索引可能会阻止查询通过扫描整个集合来查找并返回查询结果。有关索引的更多信息,请参阅MongoDB中索引的完整文档

示例
应用程序通过type字段查询inventory集合 。type字段的值是用户驱动的。

var typeValue = <someUserInput>;
db.inventory.find( { type: typeValue } );

要提高此查询的性能,请在inventory集合中的type字段上添加升序或降序索引。在mongo shell中,可以使用以下db.collection.createIndex() 方法创建索引:

db.inventory.createIndex( { type: 1 } )

该索引可以防止上面的以及type的查询通过扫描整个集合来返回结果。

要分析带有索引的查询的性能,请参阅分析查询性能
除了优化读取操作外,索引还可以支持排序操作,并可以提高存储利用率。有关索引创建的更多信息,请参见db.collection.createIndex()Indexes

  • 对于单字段索引,升序和降序之间的选择并不重要。对于复合索引,选择很重要。有关更多详细信息,请参见索引顺序

2 查询选择性

查询选择性是指查询语句排除或过滤出集合中文档的程度。查询选择性可以决定查询是否可以有效使用索引,甚至根本不使用索引。
更具选择性的查询与较小百分比的文档匹配。例如,相等匹配唯一_id字段的查询具有很高的选择性,因为它最多可以匹配一个文档。
选择性较低的查询与较大比例的文档匹配。选择性较低的查询不能有效地使用索引,甚至根本无法使用索引。
例如,不等操作符$nin和 n e 是 不 太 具 有 选 择 性 的 , 因 为 它 们 经 常 匹 配 索 引 的 一 大 部 分 。 结 果 , 在 许 多 情 况 下 , 带 有 索 引 的 ne是不太具有选择性的,因为它们经常匹配索引的一大部分。结果,在许多情况下,带有索引的 nenin或 n e 查 询 的 性 能 可 能 还 没 有 必 须 扫 描 集 合 中 所 有 文 档 的 ne查询的性能可能还没有必须扫描集合中所有文档的 nenin或$ne查询性能好。
正则表达式的选择性取决于表达式本身,有关详细信息,请参见正则表达式和索引的使用

3 覆盖查询

涵盖查询是可以完全使用索引满足的查询,而不必检查任何文档。当满足以下所有条件时,索引将 覆盖查询:

  • 查询中的所有字段都是索引的一部分,
  • 结果中返回的所有字段都在同一索引中。
  • 查询中没有字段等于null(即{“field” : null}或{“field” : {$eq : null}})。

例如,一个集合inventory在type和item字段上具有以下索引 :

db.inventory.createIndex( { type: 1, item: 1 } )

该索引将涵盖以下操作,该操作在type和item字段上查询并仅返回item字段:

db.inventory.find(
   { type: "food", item:/^c/ },
   { item: 1, _id: 0 }
)

通过指定索引形成覆盖查询,投影文档必须明确指定_id: 0从结果中排除_id字段,因为该索引不包含_id字段。
在版本3.6中更改:索引可以涵盖对嵌入式文档中的字段的查询。
例如,考虑具有以下格式的文档的集合userdata:

{ _id: 1, user: { login: "tester" } }

该集合具有以下索引:

{ "user.login": 1 }

{ “user.login”: 1 }索引将涵盖以下查询:

db.userdata.find( { "user.login": "tester" }, { "user.login": 1, _id: 0 } )

要为嵌入式文档中的字段建立索引,请使用点符号

3.1 多健覆盖

从3.6开始,如果索引跟踪导致索引为多键的一个或多个字段,则多键索引可以覆盖非数组字段的查询。在MongoDB 3.4或更高版本中,且在MMAPv1以外的存储引擎上创建的多键索引,会跟踪此数据。
多键索引不能覆盖对数组字段的查询。

3.2 性能

由于索引包含查询所需的所有字段,因此MongoDB既可以匹配查询条件 ,也可以仅使用索引返回结果。
仅查询索引比查询索引之外的文档要快得多。索引键通常比它们所分类的文档小,并且索引通常内存中可用,或者按顺序位于磁盘上。

3.3 限制

3.3.1 索引字段上的限制

  • 地理空间索引不能覆盖查询。
  • 多键索引不能覆盖对数组字段的查询。

3.3.2 分片集合中的限制

MongoDB从3.0开始,如果索引不包含片键,且在一个mongos上运行时,索引不能覆盖在分片集合上的查询,除非_id索引有以下情况:当在一个mongos上运行时,如果在分片集合的查询只规定了一个_id字段的条件,并且仅返回_id字段,即使_id字段不是分片键,_id索引也可以覆盖该查询。
在以前的版本中,索引不能覆盖在在一个mongos上运行的对一个分片集合的查询。

3.3.3 explain

要确定查询是否为覆盖查询,请使用db.collection.explain()explain() 方法,然后查看结果
db.collection.explain()提供有关其他操作执行的信息,例如db.collection.update()。有关详细信息,请参见db.collection.explain()
有关更多信息,请参见测评索引的使用(Measure Index Use)

进入MongoDB中文手册(4.2版本)目录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值