MongoDB聚合管道$匹配顺序

我有带有4个分片的MongoDB集群 . 我的分片键是:{client_id:1,date:1}使用过的集合有大约50M的文档 .

我将1个文档粘贴为样本数据:

{
        "_id" : ObjectId("54e069353e9104db470065e6"),
        "campaign_name" : "SC - Biker Planet",
        "adgroup_name" : "motociclista cerca",
        "client_id" : NumberLong(143),
        "adgroup_id" : NumberLong(28469),
        "campaign_id" : NumberLong(849),
        "device" : "desktop",
        "clicks" : NumberLong(0),
        "conv" : NumberLong(0),
        "cost" : NumberLong(0),
        "impressions" : NumberLong(1),
        "date" : ISODate("2014-02-22T05:00:00.000Z")
    }

现在,我已经安装了MongoDB 3.0 RC9(带有很好的wiredTiger存储引擎),我正在比较以下2个查询:

一个)

db.google_raw_id.aggregate([{
        $match: {
            client_id: 143,
            campaign_name: 'SC - Dating For Seniors',
            date: {
                $gte: ISODate("2014-01-10T00:00:00.0Z"),
                $lte: ISODate("2015-01-10T00:00:00.0Z")
            }
        }
    }, {
        $group: {
            _id: "$campaign_name",
            cost: {$sum: "$cost"},
            clicks: {$sum: "$clicks"},
            impressions: {$sum: "$impressions"}
        }
    }])

B)

db.google_raw_id.aggregate([{
        $match: {
            client_id: 143,
            date: {
                $gte: ISODate("2014-01-10T00:00:00.0Z"),
                $lte: ISODate("2015-01-10T00:00:00.0Z")
            }
        }
    }, {
        $group: {
            _id: "$campaign_name",
            cost: {$sum: "$cost"},
            clicks: {$sum: "$clicks"},
            impressions: {$sum: "$impressions"}
        }
    }, {
        $match: {
            _id: 'SC - Dating For Seniors',
        }
    }])

查询A需要大约0.35秒执行,查询B大约需要1.1秒,它们都返回相同的结果 . 你可以看到它们之间只有差异,我将“campaign_name”过滤器从$ group之前的$ match移动到$ group之后的$ match .

这是否可以使用,因为如果第一个$ match中没有其他过滤器,或者我在配置中出错了,则分片键{client_id,date}只能快速工作?

UPDATE

这里我解释了使用MongoDB聚合的查询A和B http://pastebin.com/8fW7G6ty

这里我有查询A和B简化使用.find()http://pastebin.com/xa7UYBuh

我也有campaign_name的索引,但是如果在第一次匹配中使用了campaign_name,则聚合查询似乎更慢,因为这不是分片键的一部分,这就是为什么Mongo必须签入多个分片 .

对我来说,这是逻辑解释,为什么查询B更快 . 在查询B中,Mongo将结果减少到较小的数据集,而不是在其上应用campaign_name,因此它更快,并且不会覆盖其他分片 . 只是我期待MongoDB可以自动找出:)

回答(1)

3 years ago

A 更快,因为在第一次'match'之后你已经 grouped 记录('match'之后的所有结果都具有相同的'campaign_name') . 在'group'只需要计算它们 .

B 较慢,因为在第一场比赛后你有 more 结果,而'group'需要处理更多数据 . 换句话说,脚本将为 all 找到的广告系列计算结果 .