引用docs:
创建索引时,与键关联的数字指定 索引的方向,因此它应始终为1(升序)或-1 (降序)。方向对于单个键索引或无关紧要 随机访问检索,但如果你正在做各种各样或重要 复合索引的范围查询。
但是,我认为没有理由为什么索引的方向对复合索引很重要。有人可以提供进一步的解释(或示例)吗?
答案 0 :(得分:94)
MongoDB以某种方式连接复合键并将其用作BTree中的键。
查找单个项目时 - 树中节点的顺序无关紧要。
如果要返回一系列节点 - 彼此靠近的元素将位于树的相同分支下方。节点越接近范围,它们就越快被检索。
使用单个字段索引 - 订单无关紧要。如果它们按升序排列在一起,它们也会按降序排列在一起。
当您有复合键时 - 订单开始变得重要。
例如,如果键是A升序B升序,则索引可能如下所示:
Row A B 1 1 1 2 2 6 3 2 7 4 3 4 5 3 5 6 3 6 7 5 1
A升序B降序的查询将需要不按顺序跳转索引以返回行并且速度会变慢。例如,它将返回Row 1, 3, 2, 6, 5, 4, 7
与索引顺序相同的远程查询将以正确的顺序依次返回行。
在BTree中查找记录需要O(Log(n))时间。按顺序查找记录范围仅为OLog(n)+ k,其中k是要返回的记录数。
如果记录乱序,则成本可能与OLog(n)* k
一样高答案 1 :(得分:42)
您正在寻找的简单答案是方向仅在您对两个或多个字段进行排序时才会起作用。
如果您要对{a : 1, b : -1}
进行排序:
索引{a : 1, b : 1}
慢于索引{a : 1, b : -1}
答案 2 :(得分:10)
了解两个要点。
索引不是免费的。它们占用内存,并在执行插入,更新和删除时强加性能损失。通常,性能损失可以忽略不计(特别是与读取性能的提升相比),但这并不意味着我们无法聪明地创建索引。
确定应将哪些字段组合在一起是为了了解您正在运行的查询。用于创建索引的字段顺序非常重要。好消息是,如果你的订单错误,那么索引根本就不会被使用,所以很容易发现解释。
您的查询可能需要排序。但是排序可能是一项昂贵的操作,因此处理您正在排序的字段非常重要,就像您要查询的字段一样。所以如果它有索引会更快。但是有一个重要的区别,您要排序的字段必须是索引中的最后一个字段。此规则的唯一例外是,如果该字段也是您查询的一部分,那么必须是最后一条规则不适用。
您可以对索引的所有键或子集指定排序;但是,排序键必须按它们在索引中显示的顺序列出。例如,索引键模式{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上的排序,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 }