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

joh*_*odo 104 sorting indexing performance query-optimization mongodb

引用文档:

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

但是,我认为没有理由为什么指数的方向应该对复合指数起作用.有人可以提供进一步的解释(或示例)吗?

Jar*_*lls 101

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

对于升序B降序的查询将需要不按顺序跳转索引以返回行并且将更慢.例如,它将返回Row1, 3, 2, 6, 5, 4, 7

与索引顺序相同的远程查询将以正确的顺序依次返回行.

在BTree中查找记录需要O(Log(n))时间.按顺序查找记录范围仅为OLog(n)+ k,其中k是要返回的记录数.

如果记录乱序,则成本可能与OLog(n)*k一样高

  • 它是性能损失的原因是因为它不仅仅是简单示例中的内存中的顺序列表.它实际上是一个加权树.跳出故障将涉及再次遍历树.RDMS最终有订单索引. (8认同)

Zai*_*sud 42

您正在寻找的简单答案是,当您在两个字段上进行排序时,方向才重要.

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

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


Som*_*luk 10

为什么索引

理解两个关键点.

  1. 虽然索引优于无索引,但正确的索引要比其中任何一个好得多.
  2. MongoDB每个查询只使用一个索引,使复合索引具有适当的字段顺序,您可能想要使用它.

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

如何索引

确定应将哪些字段组合在一起是为了了解您正在运行的查询.用于创建索引的字段顺序非常重要.好消息是,如果您的订单错误,索引将根本不会被使用,因此很容易发现解释.

为什么要排序

您的查询可能需要排序.但是排序可能是一项昂贵的操作,因此处理您正在排序的字段非常重要,就像您要查询的字段一样.所以如果它有索引会更快.但是有一个重要的区别,您要排序的字段必须是索引中的最后一个字段.此规则的唯一例外是,如果该字段也是查询的一部分,则必须是最后一条规则不适用.

怎么排序

您可以在索引的所有键或子集上指定排序; 但是,排序键必须按它们在索引中显示的顺序列出.例如,索引键模式{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 }
Run Code Online (Sandbox Code Playgroud)