127

引用文档

创建索引时,与键关联的数字指定索引的方向,因此它应始终为 1(升序)或 -1(降序)。方向对于单键索引或随机访问检索无关紧要,但如果您对复合索引进行排序或范围查询,则方向很重要。

但是,我看不出为什么指数的方向对复合指数很重要。有人可以提供进一步的解释(或示例)吗?

4

3 回答 3

124

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

查找单个项目时- 树中节点的顺序无关紧要。

如果您要返回一系列节点- 彼此靠近的元素将位于树的相同分支下。节点在范围内越近,检索它们的速度就越快。

使用单个字段索引 - 顺序无关紧要。如果它们按升序接近,它们也将按降序接近。

当您拥有复合键时 - 顺序开始变得重要。

例如,如果键是 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 降序的查询将需要乱序跳转索引以返回行并且会更慢。例如它将返回 Row1, 3, 2, 6, 5, 4, 7

与索引顺序相同的范围查询将简单地以正确的顺序依次返回行。

在 BTree 中查找记录需要 O(Log(n)) 时间。按顺序查找一系列记录只需 OLog(n) + k,其中 k 是要返回的记录数。

如果记录乱序,成本可能高达 OLog(n) * k

于 2012-04-26T09:07:53.640 回答
48

您正在寻找的简单答案是方向仅在您对两个或多个字段进行排序时才重要

如果您正在排序{a : 1, b : -1}

索引{a : 1, b : 1}索引慢{a : 1, b : -1}

于 2012-05-28T15:11:51.783 回答
16

为什么要索引

了解两个关键点。

  1. 虽然有索引比没有索引好,但正确的索引比任何一个都好得多。
  2. MongoDB 每次查询只使用一个索引,从而使复合索引具有适当的字段排序,您可能想要使用它。

索引不是免费的。它们会占用内存,并在执行插入、更新和删除时施加性能损失。通常,性能损失可以忽略不计(尤其是与读取性能的提升相比),但这并不意味着我们不能聪明地创建索引。

如何建立索引

确定应该一起索引哪组字段是关于了解您正在运行的查询。用于创建索引的字段顺序至关重要。好消息是,如果你把顺序弄错了,索引根本不会被使用,所以很容易通过解释来发现。

为什么排序

您的查询可能需要排序。但是排序可能是一项代价高昂的操作,因此将您正在排序的字段视为您正在查询的字段非常重要。所以如果它有索引会更快。但是有一个重要的区别,您要排序的字段必须是索引中的最后一个字段。此规则的唯一例外是,如果该字段也是您的查询的一部分,那么 must-be-last-rule 不适用。

如何排序

您可以对索引的所有键或子集指定排序;但是,排序键的列出顺序必须与它们在索引中出现的顺序相同。例如,索引键模式 { a: 1, b: 1 } 可以支持对 { a: 1, b: 1 } 的排序,但不支持对 { b: 1, a: 1 } 的排序。

排序必须为其所有键指定相同的排序方向(即升序/降序)作为索引键模式,或者为其所有键指定相反的排序方向作为索引键模式。例如,索引键模式 { a: 1, b: 1 } 可以支持对 { a: 1, b: 1 } 和 { a: -1, b: -1 } 的排序,但不支持对 { a: -1 ,乙: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 }
于 2016-08-11T18:42:48.107 回答