【问题标题】:mongodb indexes covering missing values覆盖缺失值的mongodb索引
【发布时间】:2020-07-22 00:16:20
【问题描述】:

我想用 mongodb 执行这种形式的高效操作:

db.getCollection('x').find({a:{$ne:null}})

我的理解是a 上的索引将不包括缺少字段a 的文档。因此{a:{$ne:null}} 形式的查询需要扫描这些文档(即不能仅仅依靠索引来查找所有匹配的文档)。

我正在考虑一项 mongo 功能请求(如果尚未提交),以允许索引选择性地包含具有缺失值的文档。我想知道:

  1. 在当前的 mongo 版本中,是否可以以某种方式加速上述查询?请注意,始终为该字段添加一个值是很好的答案,但在我的情况下这是不可能的。
  2. 这是一个合理的 mongo 功能请求吗?我不太了解索引是如何实现的,但据我所知,这似乎应该是可能的(尽管它并不适用于所有索引 - 仅适用于某些索引,由程序员自行决定)。

我知道这里有很多关于索引和“null”的问题(null 值与缺失值等),但我花了一些时间,找不到这个问题的直接答案.

作为一个真实的例子,我有一个包含大约 8000 万个文档的集合。其中大约 1,000 个文档缺少 a 字段。我希望能够遍历那些缺少a 的文档(以任何顺序)。一种解决方法是确保它们永远不会丢失a,只需将其设置为 -1 或其他特定值。这对我来说似乎有点傻 - 应该有一种方法让 mongo 在后台为我做这件事。

【问题讨论】:

  • 您最初的假设不正确。索引可以并且确实涵盖 {$ne:null} 的查询
  • 同意 - 如果它对任何人都有帮助,我正在考虑这里讨论的 COUNT_SCAN 案例mongodb-user.narkive.com/MKpJkCNh/…(但这是一个单独的问题)

标签: mongodb


【解决方案1】:

允许快速查找的索引有两个相关特性(与执行集合扫描相比):

  • 值的顺序
  • 索引值的紧凑性

如果你有值ab,你可以说ab 之前,按字典顺序。如果您有文档{a: 2, b: 5}{b: 4, a: 3},则这些文档的单一排序不能满足典型查询。例如,如果您希望对所有 a 值进行排序,那么您可能需要 2, 3,但如果您需要 b 值,则可能需要 4, 5 - 需要颠倒文档顺序。

当数据库将索引存储在磁盘上时,这些值会以 索引顺序 存储(无论特定索引可能是什么,例如排序规则都会影响这一点)。一般来说,没有单一的顺序可用于整体的集合文档,因此集合文档是无序的。

当您按索引查询时,您获取正在搜索的值并实质上使用索引执行二进制搜索,因为索引中的数据已排序。

使用索引的第二个原因是,如果您正在扫描集合,对于每个文档,通常需要从磁盘检索整个文档并跳过。如果您有 100 GB 的集合并且正在执行扫描,则可能需要跳过 100 GB 以上的数据。如果同一个集合在某个字段上有 100 MB 的索引(因为索引只存储该字段中的值而不是整个文档的数据),并且数据库执行完整的索引扫描,它只需要遍历 100 MB数据。

现在,关于在索引中存储缺少值的问题。

从索引的角度来看,不同文档中的“缺少值”是相同的值。当所有值都相同时,您将失去进行二分搜索的能力。因此,如果您正在寻找那个“缺乏价值”的文档,索引将返回集合中所有缺乏价值的文档,然后您无论如何都必须对它们进行扫描,以根据您的任何其他条件进行过滤有。由于这通常会产生较差的选择性,因此数据库不会首先使用索引并进行集合扫描。

而且,您很可能希望查询中的其他字段,而不是没有值的字段。所以现在您希望索引存储完整的文档,这违背了紧凑性的想法。

【讨论】:

  • 这通常是有道理的,但我会在我的问题中放置一个具体的真实示例来帮助澄清。我认为在我的情况下,索引会通过覆盖缺失值来大大加快速度。
  • 我相信标准答案是调整您的架构/应用程序,以便您执行正面查询而不是负面查询。例如,您可以添加另一个字段。
  • 同意有很多方法可以解决这个问题。我的数据就是这样,我觉得添加字段或更改它以解决 mongo 的技术限制并不理想。这就是为什么我认为这是对 mongo 的一个合理的功能请求(因为我可以看到他们是如何实现它的)——但我想先在这里对其进行完整性检查。我经常遇到这个特殊问题,但我当然不知道它在所有 mongo 用户的世界中有多普遍。
  • 我看不出这个答案是“正确的” - MongoDB 中的索引支持查询 $ne:null 并且它们确实涵盖了它们。
  • 我认为令人困惑的部分是关于 $ne:null 获取当前值和存储缺失值的问题。
猜你喜欢
  • 1970-01-01
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-03
  • 2011-05-09
  • 1970-01-01
相关资源
最近更新 更多