【问题标题】:runtime of using indexing in mongodb在 mongodb 中使用索引的运行时
【发布时间】:2012-10-25 17:57:57
【问题描述】:

基于mongodbdocumentation

ensureIndex() 函数仅在索引不存在时创建索引。

一旦一个集合被一个键索引,随机访问匹配的查询表达式 指定的键很快。如果没有索引,MongoDB 必须遍历每个文档来检查查询中指定键的值:

db.things.find({j:2});  // fast - uses index
db.things.find({x:3});  // slow - has to check all because 'x' isn't 

这是否意味着第一行代码运行时是big_theta = 1,第二行代码是big_theta = n

【问题讨论】:

  • @SergioTulentsev 你应该发布作为答案,并获得积分! :)
  • @LaneLane:太晚了,已经有答案了:)

标签: algorithm mongodb indexing runtime


【解决方案1】:

B-tree 是 O(log N),Emil Vikström 对 O(1) 的回答完全不正确。即使在他的“动机”(或假设)下,它也是错误的:他忘记了为每个节点搜索 8192 个子节点的时间。换句话说,如果 K 是节点的大小,D 是树的深度,则时间复数可以重新表示为 O(D) + O(log K)(相当于 O(log N)) ,如果孩子被组织为 BST 或类似的对数结构。

【讨论】:

  • 你在数学上是正确的,我确实用它来打开我的答案。我的动机是确切的渐近运行时在实践中是无关的。您可以使用21 levels 索引已知宇宙中的所有原子。我没有忽略搜索孩子的时间,这个数字是有界的,因此每个节点中的 O(1)。
【解决方案2】:

MongoDB 使用 B-tree 进行索引,如 index.cpp 的源代码所示。这意味着查找可以表示为O(log N),其中 N 是文档数,但如果 D 是树的深度(假设树有点平衡),它也是 O(D)。 D 通常非常小,因为每个节点都会有很多子节点。

MongoDB 中一个节点中的子节点数约为 8192 (btree.h),因此包含几 十亿 个文档的索引可能适合只有 3 级的树!您很容易意识到对数不是 log_2(如在二叉树中),而是 log_8192,它的增长非常缓慢。

因此,b-trees 在实践中通常被视为常量时间查找,O(1)

在每个节点中保留许多子节点的另一个很好的原因是索引存储在磁盘上。您想尝试为一个节点利用磁盘块中的所有空间来提高缓存性能并减少磁盘寻道。 B 树的磁盘性能非常好,因为您只需要访问很少的节点即可找到您要查找的内容。

【讨论】:

  • 作为开发者有什么办法可以保证每个节点有很多子节点,还是mongodb做的​​?
  • 这是由 btree 实现完成的。我没有专门研究过 MongoDB(除了这篇文章的源代码略读),但他们很聪明,所以我猜他们在平衡和分布方面做了一些事情。
  • 在回答中编辑了模棱两可的陈述。它不是 O(1) 查找。见:en.wikipedia.org/wiki/B-tree
  • Manav,如果您仔细阅读我的回答,您会发现我的陈述是我的动机。我也已经说过它是对数的,但对数增长非常缓慢。所以编辑它会完全改变答案的意图。只需投票您认为正确的答案即可。 (但请记住,在每个节点中有 8k 个子节点的平衡 b 树中,大多数人永远不会达到 4 个级别,更不用说 5 或 6 个。那么对数在这里真的很重要吗?)。我也可以诉诸权威:我的动机是从我在乌普萨拉大学的 DB 教授那里抄来的 :-)
【解决方案3】:

Mongo 索引是 B 树,因此索引查找是 O(log n)。未索引的查找是O(n)

【讨论】:

  • 有没有办法进一步减少索引查找运行时间?
  • 减少 n。除此之外,没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 2022-08-18
  • 2016-07-08
  • 2012-01-16
  • 1970-01-01
相关资源
最近更新 更多