虚位以待(AD)
虚位以待(AD)
首页 > 数据库 > MongoDB数据库 > MongoDB数据库学习-聚集-聚集管道优化

MongoDB数据库学习-聚集-聚集管道优化
类别:MongoDB数据库   作者:码皇   来源:<a href="http://blog.csdn.net/chunyuan314" target="_blank" rel="nofollow   点击:

MongoDB数据库学习-聚集-聚集管道优化。

MongoDB数据库学习-聚集-聚集管道优化。

 聚集管道优化

聚集管道操作有一个优化阶段,试图重组管道以提高性能。

要查看优化器如何变换一个特定的聚集管道,在db.collection.aggregate()方法中包括explain选项。

优化操作因版本的不同而不同。

 投影优化

聚集管道可以确定它是否只需要文档字段的一个子集来获取结果,如果是的化,管道只会使用这些必需的字段,减少的通过管道的数据量。

 管道序列优化

$sort + $match序列优化

当$sort后面跟着$match的时候,$match会被移到$sort前,以最小化排序的数据量。例如,如果管道由以下步骤组成:

    {
    $sort: {
    age : -1 }
    }
    ,{
    $match: {
    status: '
    A'
    }
    }

在优化阶段,优化器把序列变成如下:

    {
    $match: {
    status: '
    A'
    }
    }
    ,{
    $sort: {
    age : -1 }
    }

$skip+$limit序列优化

当$skip后面有$limit的时候,$limit会被移到$skip前面。重排之后,$limit的值要增加$skip的量。

例如,如果管道由以下步骤组成:

    {
    $skip: 10 }
    ,{
    $limit: 5 }

在优化阶段,优化器会把序列变成如下:

    {
    $limit: 15 }
    ,{
    $skip: 10 }

对于$sort+$limit的组合,优化操作允许有更多的机会,例如对于$sort+$skip+$limit序列。

对于在分片集合上的聚集操作,该优化减少了从每个分片上返回的结果。

$redact+$match序列优化

只要有可能,当管道的$redact阶段后面直接跟着$match阶段的时候,该聚集操作有时可以把$match阶段的一部分添加到$redact阶段之前。如果所添加的$match阶段在管道的开始,该聚集操作可以使用索引来查询集合以限制进入管道的文档数量。更多信息请查看管道操作符与索引

例如,如果管道由以下阶段组成:

    {
    $redact: {
    $cond: {
    if: {
    $eq: [ "$level", 5 ] }
    , then: "$$PRUNE", else: "$$DESCEND" }
    }
    }
    ,{
    $match: {
    year: 2014, category: {
    $ne: "Z" }
    }
    }

优化器可以把$match阶段添加到$redact阶段之前:

    {
    $match: {
    year: 2014 }
    }
    ,{
    $redact: {
    $cond: {
    if: {
    $eq: [ "$level", 5 ] }
    , then: "$$PRUNE", else: "$$DESCEND" }
    }
    }
    ,{
    $match: {
    year: 2014, category: {
    $ne: "Z" }
    }
    }

$project+$skip或$limit序列优化

版本3.2新增。

当$project后面跟着$skip或者$limit的时候,$skip或$limit可以移到$project之前。例如,如果管道由以下阶段组成:

    {
    $sort: {
    age : -1 }
    }
    ,{
    $project: {
    status: 1, name: 1 }
    }
    ,{
    $limit: 5 }

在优化阶段,优化器把序列变成:

    {
    $sort: {
    age : -1 }
    }
    ,{
    $limit: 5 }
    {
    $project: {
    status: 1, name: 1 }
    }
    ,

管道合并优化

如果有可能,优化阶段会把一个管道阶段合并到它前面那一个去。一般地,合并操作出现在任何一个序列重组优化之后。

$sort+$limit合并

当$sort直接放在$limit前面的时候,优化器可以把$limit合并到$sort里面。这使得排序操作只保留前n个结果,n是limit所指定的值,MongoDB只需要在内存中保留n条数据。查看$sort操作符和内存获取更多信息。

$limit+$limit合并

当一个$limit后直接跟着另一个$limit时,这两个阶段可以合并成一个$limit,limit数量是两个初始limit数量的较小值。例如,一个管道包含如下序列:

    {
    $limit: 100 }
    ,{
    $limit: 10 }

第二个$limit阶段可以合并到第一个$limit阶段,结果只剩一个$limit阶段,limit数量是10,是这两个limit中的较小值。

    {
    $limit: 10 }

$skip+$skip合并

当一个$skip后面直接跟着另一个$skip时,这两个阶段可以合并成一个$skip阶段,skip的数量是两个skip数量之和。例如,一个管道包含如下序列:

    {
    $skip: 5 }
    ,{
    $skip: 2 }

第二个$skip可以合并至第一个$skip,结果只有一个$skip阶段,skip的数量是7,即这两个skip的数量之和:

    {
    $skip: 7 }

$match+$match合并

当一个$match后面直接跟着另一个$match时,这两个阶段可以合并成一个$match,用$and操作符把它们的条件组合起来。例如,一个管道包含如下序列:

    {
    $match: {
    year: 2014 }
    }
    ,{
    $match: {
    status: "A" }
    }

第二个$match可以合并至第一个$match,结果只有一个$match阶段:

    {
    $match: {
    $and: [ {
    "year" : 2014 }
    , {
    "status" : "A" }
    ] }
    }

$lookup+$unwind合并

版本3.2新增。

当一个$unwind直接跟着$lookup时,并且$unwind直接对$lookup的as字段操作,优化器就可以把$unwind合并至$lookup阶段内,这避免了创建大量的中间文档。

例如,一个管道包含如下序列:

    {
    $lookup: {
    from: "otherCollection", as: "resultingArray", localField: "x", foreignField: "y" }
    }
    ,{
    $unwind: "$resultingArray"}

优化器可以把$unwind阶段合并至$lookup阶段。如果你用explain选项运行这个聚集,explain输出如下的合并阶段:

    {
    $lookup: {
    from: "otherCollection", as: "resultingArray", localField: "x", foreignField: "y", unwinding: {
    preserveNullAndEmptyArrays: false }
    }
    }

例子

以下例子是一些既可以用序列重排,又可以合并的序列。一般地,合并发生在序列重排之后。

$sort+$skip+$limit序列

一个管道包含如下序列:$sort后面跟着$skip,然后跟着$limit:

    {
    $sort: {
    age : -1 }
    }
    ,{
    $skip: 10 }
    ,{
    $limit: 5 }

首先,优化器执行$skip+$limit序列优化,把序列变成如下:

    {
    $sort: {
    age : -1 }
    }
    ,{
    $limit: 15 }
    {
    $skip: 10 }

重排时,$skip+$limit序列优化增加了$limit的量。详情请看$skip+$limit序列优化

重排之后,$sort直接在$limit之前了,管道就可以把这两个阶段合并,以减少排序操作过程中的内存占用。更多请查看$sor$limit合并

$limit+$skip+$limit+$skip序列

一个包含$limit和$skip阶段交替的序列的管道。

    {
    $limit: 100 }
    ,{
    $skip: 5 }
    ,{
    $limit: 10 }
    ,{
    $skip: 2 }

$skip+$limit序列优化把{$skip: 5}与{$limit: 10}的位置交换以下,增加limit的量:

    {
    $limit: 100 }
    ,{
    $limit: 15}
    ,{
    $skip: 5 }
    ,{
    $skip: 2 }

优化器然后把这两个$limit阶段合并成一个$limit阶段,把两个$skip阶段合并成一个$skip阶段,结果序列如下:

    {
    $limit: 15 }
    ,{
    $skip: 7 }
相关热词搜索: