Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MongoDB$或+;排序+;指数如何避免在内存中排序?_Mongodb_Sorting_Indexing - Fatal编程技术网

MongoDB$或+;排序+;指数如何避免在内存中排序?

MongoDB$或+;排序+;指数如何避免在内存中排序?,mongodb,sorting,indexing,Mongodb,Sorting,Indexing,我有一个问题,为我的mongo查询生成适当的索引,这将避免排序阶段。我甚至不确定在我的情况下这是否可行。下面是我对执行统计数据的查询: db.getCollection('test').find( { "$or" : [ { "a" : { "$elemMatch" : { "_id" : { "$in" : [4577] } } }, "b" : { "$in" : [290] }, "c" : { "$in" : [35,

我有一个问题,为我的mongo查询生成适当的索引,这将避免排序阶段。我甚至不确定在我的情况下这是否可行。下面是我对执行统计数据的查询:

db.getCollection('test').find(
{
    "$or" : [
    {
        "a" : { "$elemMatch" : { "_id" : { "$in" : [4577] } } }, 
        "b" : { "$in" : [290] }, 
        "c" : { "$in" : [35, 49, 57, 101, 161, 440] }, 
        "d" : { "$lte" : 399 }
    },
    { 
        "e" : { "$elemMatch" : { "numbers" : { "$in" : ["1K0407151AC", "0K20N51150A"]  } } },
        "d" : { "$lte" : 399 }
     }] 
})
.sort({ "X" : 1, "d" : 1, "Y" : 1, "Z" : 1 }).explain("executionStats")
字段“m”、“a”和“e”是数组,这就是为什么“m”不包含在任何索引中的原因

如果您查看屏幕截图,您将看到内存使用率非常接近最大值,不幸的是,我遇到过由于32MB限制而无法执行查询的情况

$or查询第一部分的索引: { “a._id”:1, “X”:1, “d”:1, “Y”:1, “Z”:1, “b”:1, “c”:1 }

$or查询第二部分的索引: { “e.数字”:1, “X”:1, “d”:1, “Y”:1, “Z”:1 }

索引用于查询,但不用于排序。而不是排序阶段,我也希望看到排序合并阶段,但目前没有成功。如果我在$或单独运行部件查询,它们可以使用索引来避免在内存中排序。作为一种解决方法,它是可以的,但是我需要合并并利用应用程序的结果

MongoDB版本是3.4.2。我检查并提问。我的问题是结果。也许我错过了什么

编辑:mongo文档如下所示:

{
    "_id" : "290_440_K760A03",
    "Z" : "K760A03",
    "c" : 440,
    "Y" : "NPS",
    "b" : 290,
    "X" : "Schlussleuchte",
    "e" : [ 
        {
            "..." : 184,
            "numbers" : [ 
                "0K20N51150A"
            ]
        }
    ],
    "a" : [ 
        {
            "_id" : 4577,
            "..." : [ 
                {
                    "..." : [ 
                        {
                            "..." : "R",
                        }
                    ]
                }
            ]
        }, 
        {
            "_id" : 4578            
        }
    ],
    "d" : 101,
    "m" : [ 
        "AT", 
        "BR", 
        "CH"
    ],
    "moreFields":"..."
}
编辑2:从查询中删除字段“m”,以降低复杂性,并为需要帮助的人转储测试集合:)

以下是解决方案- 我刚刚在我的测试集合中添加了一个文档,如您的问题(编辑部分)所示。然后我创建了以下四个索引-

 1. {"m":1,"b":1,"c":1,"X":1,"d":1,"Y":1,"Z":1}
 2. {"a._id":1,"b":1,"c":1,"X":1,"d":1,"Y":1,"Z":1}
 3. {"m":1,"X":1,"d":1,"Y":1,"Z":1}
 4. {"e.numbers":1,"X":1,"d":1,"Y":1,"Z":1}
当我为执行统计数据执行给定的查询时,它会显示预期的排序合并状态

这是解释- MongoDB有一个叫做的东西,它告诉我们应该如何创建索引。我只是遵循这个规则,并保持索引的顺序。所以这里的索引应该是
{相等字段,X:1,d:1,Y:1,Z:1,范围字段}
。您可以看到,查询仅在字段“d”上有范围(
“d”:{“$lte”:101}
),但索引的排序字段(
“X”:1,“d”:1,“Y”:1,“Z”:1
)中已经包含了“d”,因此我们可以从索引末尾跳过范围部分(即字段“d”)

如果“d”不在排序/相等谓词中,那么我会在范围索引字段的索引中使用它,并且我的索引看起来像
{equality fields,“X”:1,“Y”:1,“Z”:1,“d”:1}

现在我的索引是
{equalityfields,“X”:1,“d”:1,“Y”:1,“Z”:1}
,我只关心equalityfields。为了找出相等字段,我只检查了查询find谓词,发现有两个条件由OR运算符组合而成

  • 第一个条件在
    “a._id”,“b”,“c”,“m”上相等(“d”具有范围,而不是相等)。所以我需要创建一个类似于a._id:1,“m”:1,“b”:1,“c”:1,“X”:1,“d”:1,“Y”:1,“Z”:1的索引,但这会产生错误,因为它有两个数组字段“a_id”和“m”。我们知道Mongo不允许,所以它会失败。所以我创建了两个单独的索引,以允许Mongo使用QueryPlanner选择的任何内容。因此我创建了第一个和第二个索引
  • OR运算符的第二个条件为“e.number”和“m”。这两个都是数组字段,所以我必须像第一个条件一样创建两个索引,这就是我获得第三个和第四个索引的原因
现在我们知道单个查询一次只能使用一个索引,所以我需要创建这些索引,因为我不知道将执行OR运算符的哪个分支


注意:若您关心索引的大小,那个么前两个索引中只能保留一个,后两个索引中只能保留一个。或者,您也可以保留所有四个索引,并提示mongo使用适当的索引(如果您在查询计划器之前很清楚的话)。

根据您链接到的第一个问题中的答案,两个索引都需要以
“X”:1,“d”:1,“Y”:1,“Z”:1
结尾进行排序合并,而不仅仅包含这些字段。@JohnnyHK,将第一个索引更改为
{“a._id:1,X:1,d:1,Y:1,Z:1}”
尝试是否有效,但没有成功。排序仍在内存中,查询速度变慢。能否添加一个或两个data@lovegupta,如果你是指文档,那么请查看更新的问题。注释长度不够。你可以尝试创建以下四个索引,看看它是否适用于你。它适用于我,我得到了排序合并.1.{“m”:1,“b”:1,“c”:1,“X”:1,“d”:1,“Y”:1,“Z”:1}2.{“a.id”:1,“b”:1,“c”:1,“X”:1,“d”:1,“Y”:1}3.{“m”:1,“X”:1,“d”:1,“Y”:1,“Z”:1}4.{“e.数字”:1,“X”:1,“d”:1,“Y”:1,“Z”:1}4我编辑了我的问题并添加了一个测试集合。现在可以删除索引1和3。不幸的是,即使我像您的答案中那样更改了索引2,我仍然有排序阶段。使用此索引2,您将在$or查询的第一部分有排序合并阶段(
“a”:{“$elemMatch”:{“\u id”:{“$in:[4577]}},“b”:{“$in”:[290],[c]:{“$in”:[35,49,57,101,161,440],[d]:{“$lte:399}
),如果您使用以下索引,您可以完全避免:{“a.”id:1,“X”:1,“d”:1,“Y”:1,“Z”:1,“b”:1,“c”:1}。评论的大小不够,所以我将发布第二条:)你说的关于平等排序范围的事情是正确的,但可能你有点误解。请阅读本文:无论如何,我想再次感谢你的时间。感谢stoos提供链接并更正我。你的问题是否仍然存在,或者它是否如你所期望的那样工作?不幸的是当然,它仍然是开放的。我会继续努力解决这个问题后Holyday。我会更新的问题,如果我发现新的东西。