Mongodb 聚合管道优化 - $match 的 2 阶段

Posted

技术标签:

【中文标题】Mongodb 聚合管道优化 - $match 的 2 阶段【英文标题】:Mongodb aggregation pipeline optimization - 2 stage of $match 【发布时间】:2019-06-10 15:00:28 【问题描述】:

我最近在研究聚合管道的性能优化。在决定要索引哪个时,我遇到了这个问题。我为 'receiverId': 1,'type': 1 设置了一个复合索引。 我原来的管道是这样的。我正在考虑是否索引isRead 也是必要的。我之所以没有创建三字段复合索引是因为其他查询只使用了recieverIdtype

notifications.aggregate([
        $match: 
            'recieverId': ObjectId(xxx),
            'type': xxx,
            'isRead': false
        
    ,
    
     ...
    ,
], (err, result) => 
    return res.status(200).json(result);
);

所以,我在下面改了这个。想知道这样的管道在过滤recieverIdtype 后是否可以节省一些计算成本。 isRead, 第二个 $match 是否会从第一个 $match 的结果中过滤?

notifications.aggregate([
        $match: 
            'recieverId': ObjectId(xxx),
            'type': xxx,
        
    ,
    
        $match: 
            'isRead': false
        
    ,
    
     ...
    ,
], (err, result) => 
    return res.status(200).json(result);
);

【问题讨论】:

【参考方案1】:

实际上,您如何编写并不重要,因为 mongo 会优化此管道。

来自文档:

当一个 $match 紧跟另一个 $match 之后,这两个阶段可以合并为一个 $match。

阅读有关它和其他管道优化 mongo 所做的here。

【讨论】:

感谢链接,我读到了,我还在工作室 3T 中进行了管道测试,但仍在考虑是否创建包含 isRead 字段的复合索引,因为每当用户使用时,该值都会改变阅读。对上述查询有何建议? isRead 字段添加到您的索引将有助于mongo,因为它不需要过滤它。这意味着它将有助于运行时。需要考虑的一件事(这对大多数人来说不是问题)是索引大小,在这种情况下应该不会有太大的不同。 感谢,最后一个问题,例如,我总共有5个查询,前4个只查询recieverIdtype字段,只有最后一个查询三个字段recieverIdtype & `isRead',一个复合索引(3个字段)是否足以支持所有5个查询? 是(取决于索引构建顺序),例如索引x, y, z 可以支持对xx,yx,y,z 的查询。也阅读了这个here。

以上是关于Mongodb 聚合管道优化 - $match 的 2 阶段的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB $geoNear 聚合管道(使用查询选项和使用 $match 管道操作)给出不同的结果

MongoDb 聚合 $match 错误:“参数必须是聚合管道运算符”

MongoDB 聚合管道 $match order

Mongodb - 解决 ( aggregate聚合管道 ) $match 根据 id 匹配 返回 [ ] 的问题

MongoDB的聚合操作

通过 mongo 聚合管道使用 $match 两次