为什么MongoDB中的索引方向很重要?

引用文档 :

创build索引时,与键关联的数字指定索引的方向,所以它应该始终为1(升序)或-1(降序)。 方向对单键索引或随机访问检索无关紧要,但对于复合索引进行sorting或范围查询非常重要。

但是,我看不出为什么指数的方向对复合指标有影响。 有人可以提供进一步的解释(或例子)?

MongoDB以某种方式连接复合键,并将其用作BTree中的键。

find单个项目时 – 树中节点的顺序是不相关的。

如果你正在返回一系列节点 – 彼此靠近的元素将在树的同一分支上。 节点越接近该范围,其检索速度就越快。

使用单个字段索引 – 订单无关紧要。 如果他们靠近在一起,他们也将按照降序排列在一起。

当你有一个复合键 – 订单开始重要。

例如,如果键是A升序B升序索引可能看起来像这样:

行AB
 1 1 1
 2 2 6
 3 2 7 
 4 3 4
 5 3 5
 6 3 6
 7 5 1

A递增B递减的查询将需要跳过索引以返回行,并且将变慢。 例如,它将返回第1,3,2,6,5,4,7行

按照与索引相同的顺序进行的范围查询将按照正确的顺序依次返回行。

在BTree中查找logging需要O(Log(n))时间。 按顺序查找logging范围只有OLog(n)+ k,其中k是要返回的logging数。

如果logging无序,则成本可能高达OLog(n)* k

你正在寻找的简单答案是, 当你在两个领域进行sorting时 ,方向才是重要的

如果您在{a : 1, b : -1}上sorting:

索引{a : 1, b : 1} 将比索引{a : 1, b : -1}

为什么索引

了解两个关键点。

  1. 虽然一个指数比没有指数好,但正确的指数比两者都好。
  2. MongoDB只会为每个查询使用一个索引,从而使得复合索引具有适当的字段顺序,您可能要使用它。

索引不是免费的。 他们需要记忆,并在插入,更新和删除时施加性能损失。 通常情况下,性能受到的影响可以忽略不计(特别是与读取性能的提高相比),但这并不意味着我们不能够聪明地创build索引。

如何索引

识别哪些字段应该被编入索引是关于理解您正在运行的查询。 用于创build索引的字段顺序非常重要。 好消息是,如果订单错了,索引根本就不会使用,所以很容易find答案。

为什么sorting

您的查询可能需要sorting。 但sorting可能是一个昂贵的操作,所以处理你正在sorting的字段就像你正在查询的字段一样重要。 所以如果有索引会更快。 不过,有一个重要的区别,您正在sorting的字段必须是您的索引中的最后一个字段。 这个规则的唯一例外是,如果该字段也是查询的一部分,那么必须是最后的规则不适用。

如何sorting

您可以指定索引的所有键或子集上的sorting; 但是,sorting键必须按照它们在索引中出现的顺序列出。 例如,索引关键字模式{a:1,b:1}可以支持{a:1,b:1}sorting,但不支持{b:1,a:1}。

对于所有的键,sorting必须指定相同的sorting方向(即上升/下降)作为索引键模式,或者将其所有键的相反sorting方向指定为索引键模式。 例如,索引键模式{a:1,b:1}可以支持{a:1,b:1}和{a:-1,b:-1}上的sorting,但不支持{a:-1 ,b:1}。

假设有这些索引:

 { a: 1 } { a: 1, b: 1 } { a: 1, b: 1, c: 1 } Example Index Used db.data.find().sort( { a: 1 } ) { a: 1 } db.data.find().sort( { a: -1 } ) { a: 1 } db.data.find().sort( { a: 1, b: 1 } ) { a: 1, b: 1 } db.data.find().sort( { a: -1, b: -1 } ) { a: 1, b: 1 } db.data.find().sort( { a: 1, b: 1, c: 1 } ) { a: 1, b: 1, c: 1 } db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } ) { a: 1, b: 1 }