Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.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 - Fatal编程技术网

在MongoDB';中使用阶段之间的投影是否有内存性能优势;什么是聚合管道?

在MongoDB';中使用阶段之间的投影是否有内存性能优势;什么是聚合管道?,mongodb,Mongodb,一个集合可能有多个列,每个列包含大量数据,如文章内容或图像数据等 在使用聚合管道阶段时,我假设使用投影减少字段会有好处,因此我们只将所需字段传递给后续阶段,以帮助提高内存使用率 一个简单的例子:我们需要从作者集合中查找所有没有匹配作者的文章。我会假设我们不会投射不必要的文章字段。同样的$lookup也适用于作者,我们只需要和id就可以了。演示: db.getCollection("articles").aggregate( [ { $match:

一个集合可能有多个列,每个列包含大量数据,如文章内容或图像数据等

在使用聚合管道阶段时,我假设使用投影减少字段会有好处,因此我们只将所需字段传递给后续阶段,以帮助提高内存使用率

一个简单的例子:我们需要从
作者
集合中查找所有没有匹配作者的
文章
。我会假设我们不会投射不必要的文章字段。同样的
$lookup
也适用于作者,我们只需要和id就可以了。演示:

db.getCollection("articles").aggregate(

    [
        {
            $match: {
                somecolumn: { "$ne": null, $exists: true }
            }
        },

        {
            $project: { 
                id: 1,
                authorId: 1
            }
        },

        {
            $lookup: {
                      from: "authors",
                      let: { author: "$authorId" },
                      pipeline: [
                        {
                          $match: {
                              $expr:
                                {
                                    $eq: ["$$author","$id"] }
                              }

                        },
                        { $project: { id: 1, } }
                      ],
                      as: "author"
                    }
        },

        {
            $match: {
                "author.0": {$exists: false}
            }
        }
    ]
);
我的假设正确吗,还是内部流程的工作方式不同

在使用聚合管道阶段时,我假设 使用投影缩小字段的好处,因此我们只通过 后续阶段的必填字段,以帮助提高内存使用率

是的,这是正确的。每个聚合阶段都有一个内存限制,在该限制内工作将确保不会出现性能问题

从手册()中:

管道级的RAM限制为100 MB。如果是舞台 如果超过此限制,MongoDB将产生错误。考虑到 处理大型数据集时,请使用
allowDiskUse
选项启用 将数据写入临时文件的聚合管道阶段

当查询使用
allowDiskUse
时,它会影响性能,因为使用磁盘比使用内存慢得多

此外,以下是一些重要的实践:

  • 使用尽可能少的阶段;更多阶段意味着文件 需要在每个阶段进行检查。这是额外的处理和维护 资源
  • 避免不必要的
    $project
    阶段
  • 在管道开始时指定某些阶段很重要。阶段,
    $match
    $sort
    只能在初始阶段使用索引。另外,
    $match
    $limit
    如果在管道早期使用,可以减少管道中要处理的文档数量
  • 使用
    explain
    并研究查询计划,以确定是否正在使用索引(在
    $match
    $sort
    中)或是否需要为查询优化定义任何索引。请注意,索引与聚合的工作方式略有不同,而且并非所有阶段都可以使用索引

因此,聚合框架可以自动重新安排某些阶段进行优化。有关更多详细信息,请参阅上的本文档。

通常,您希望将$project放在最后一个阶段,以便只将所需字段返回给客户端,在某些情况下可能会重命名或重新计算它们

您不需要在管道的前面有$project来“修剪字段”,因为和只获取管道中需要的字段

下面是一个示例,通过
explain
显示:

db.foo.explain().aggregate({$group:{_id:"$fieldA", count:{$sum:1}}})
{
  "stages" : [
    {
        "$cursor" : {
            "query" : {

            },
            "fields" : {
                "fieldA" : 1,
                "_id" : 0
            },
            "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "snv.foo",
                "indexFilterSet" : false,
                "parsedQuery" : {

                },
                "winningPlan" : {
                    "stage" : "EOF"
                },
                "rejectedPlans" : [ ]
            }
        }
    },
    {
        "$group" : {
            "_id" : "$fieldA",
            "count" : {
                "$sum" : {
                    "$const" : 1
                }
            }
        }
    }
  ]
}
即使我没有投影,您也可以看到只有
fieldA
被返回到管道的其余部分


唯一需要添加早期
$project
阶段的场景是解决聚合自身依赖性分析中的缺陷或限制,但应定期避免。

谢谢,实际上,我浏览了文档,但错过了“请您更新您的答案以包含该链接以帮助其他用户”部分。再次感谢!这个答案是不正确的,我正在写一个备选答案,但我只是想指出这一点。请参阅我的答案,了解为什么不应包含不必要的额外$project阶段。请注意,100MBs限制仅适用于阻塞阶段(即分组、对完整结果集排序),而不适用于通过管道传递文档的流式阶段。您的投影不是合法语法-您不能混合包含和排除。你实际使用的是哪一个?@AsyaKamsky现场,我输入了一个错误的伪示例。我已经适应了。感谢您,我建议您不要使用“author.0”:{$exists:false}只需使用{“author”:{$ne:[]}按照内部工作方式,执行普通(localField/foreignField)$lookup会更快,而且不用担心$lookup中的$project,而不用切换到更昂贵的表达式$lookup来添加投影。在下一个主要版本之前的所有版本中都是这样的,而且在未来也很可能保持这种状态。我刚刚测试了这个,我的计划不太一样。如果我在第2阶段将
$project
留在中,我会得到:
{“stages”:[{“$cursor”:{“query”:{“postCode”:{“$ne”:null,“$exists”:true}},,“fields”:{“postCode”:1.0,“_id”:1.0},“queryPlanner”:{
其中包括通常不包括的fields对象。在第2阶段排除
$project
,我得到:
{“stages”:[{“$cursor”:{“query”:{“postCode”:{“$ne”:null,$exists:true}},“queryPlanner”:{
字段对象缺失的地方。没有$project的示例管道实际上保留了所有字段。因此,没有字段对象被传递到查询子系统。我的使用$group,因此只需要一个字段。这就是为什么我说,如果您确实需要更改应返回的字段,请在最后阶段进行更改。是的,更正它保留了所有字段我想这意味着他们都进入了下一个阶段?我们能把这件事简单地说一下吗