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

为什么索引的方向在MongoDB中很重要?,mongodb,performance,sorting,indexing,query-optimization,Mongodb,Performance,Sorting,Indexing,Query Optimization,引述: 创建索引时,与键关联的数字指定 索引的方向,因此它应始终为1(升序)或-1 (下降)。方向对于单键索引或 随机访问检索,但如果您正在进行排序或 复合索引上的范围查询 然而,我看不出索引的方向对复合索引有什么影响。是否有人可以提供进一步的解释(或示例)?MongoDB以某种方式连接复合键,并将其用作BTree中的键 查找单个项目时-树中节点的顺序无关 如果返回一系列节点-彼此靠近的元素将位于树的相同分支下。节点在范围内越近,检索它们的速度就越快 使用单个字段索引-顺序无关紧要。如果它们按升

引述:

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


然而,我看不出索引的方向对复合索引有什么影响。是否有人可以提供进一步的解释(或示例)?

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

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

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

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

当您有一个复合键时-顺序开始起作用

例如,如果键是升序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排 1 1 1 2 2 6 3 2 7 4 3 4 5 3 5 6 3 6 7 5 1 对于升序B和降序B的查询将需要按顺序跳转索引以返回行,并且速度会较慢。例如,它将返回行
1、3、2、6、5、4、7

与索引顺序相同的范围查询只需按正确顺序返回行

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


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

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

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

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

为什么索引慢 理解两个关键点

  • 虽然一个索引比没有索引好,但正确的索引比任何一个都好
  • 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 }
    

    生成的行可能应该是
    1,3,2,6,5,4,7
    ?我仍然看不出它变慢的原因。只有算法应该是不同的(对于A中的每组值,它应该跳转到组的末尾,并以相反的顺序处理),但是由于MongoDB索引位于内存中,因此对速度没有明显的影响。此外,RDBMS对索引的方向一无所知,情况与afaik非常相似?它之所以会影响性能,是因为它不像简化的示例那样只是内存中的顺序列表。它实际上是一棵加权树。无序跳跃将涉及再次遍历树。RDM确实具有索引的顺序。从BTree中按顺序获取节点非常简单,只需沿着每个叶子移动,直到用完为止,然后向上移动一个级别,再向下移动下一个分支。它的O(n)的秩序,这是更多的CPU密集型。感谢进一步澄清。我检查了文档-确实可以指定索引方向,但该设置被忽略。@MarkPieszak,因为整个排序必须在创建索引的内存中完成useless@Sammaye我认为这是一个正确的想法,尽管我不确定它是否是全部。我必须查看实现才能知道它是如何工作的,但我认为结果可以单独按a排序,然后额外的b排序需要在内存中进行。嗯,奇怪的是,上次我检查代码时,它放弃了部分排序,因为排序是如何的,如果我在
    {a:-1,b:-1}
    上排序,我应该有
    {a:-1,b:-1}
    索引还是
    {a:1,b:1}
    就足够了。@Hussain在你的例子中是
    {a:1,b:1}<