MongoDB聚合管道$匹配顺序
我有4个碎片的MongoDB集群。我的分片密钥是:{client_id:1,date:1} 使用过的集合有大约50米的文档 我将粘贴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") } { “_id”:ObjectId(“54e069353e9104db470065e6”), “运动名称”:“SC-自行车星球”, “adgroup_name”:“Motocicilista cerca”, “客户id”:编号长(143), “adgroup_id”:数字长(28469), “活动id”:编号长(849), “设备”:“桌面”, “点击次数”:数字长(0), “conv”:数字长(0), “成本”:数字长(0), “印象”:数字长(1), “日期”:ISODate(“2014-02-22T05:00:00.000Z”) } 现在,我已经安装了MongoDB 3.0 RC9(带有伟大的wiredTiger存储引擎),我正在比较以下两个查询: (A) db.google\u raw\u id.aggregate([{ $match:{ 客户编号:143, 活动名称:“SC-老年人约会”, 日期:{ $gte:ISODate(“2014-01-10T00:00:00.0Z”), $lte:ISODate(“2015-01-10T00:00:00.0Z”) } } }, { $group:{ _id:“$campaign_name”, 成本:{$sum:“$cost”}, 点击:{$sum:$clicks}, 印象:{$sum:$impressions} } }]) 及 (B) db.google\u raw\u id.aggregate([{ $match:{ 客户编号:143, 日期:{ $gte:ISODate(“2014-01-10T00:00:00.0Z”), $lte:ISODate(“2015-01-10T00:00:00.0Z”) } } }, { $group:{ _id:“$campaign_name”, 成本:{$sum:“$cost”}, 点击:{$sum:$clicks}, 印象:{$sum:$impressions} } }, { $match:{ _id:‘SC-老年人约会’, } }]) 查询A执行大约需要0.35秒,查询B执行大约需要1.1秒,它们都返回相同的结果。 正如您所看到的,它们之间的唯一区别是我将“campaign_name”过滤器从$group之前的$match移动到$group之后的$match 由于只有在第一个$match中没有其他筛选器,或者我的配置中有错误,所以碎片密钥{client_id,date}才能快速工作,所以使用这种方法可以吗 更新 这里我解释了使用MongoDB聚合的查询A和查询B 这里我简化了查询A和查询B以供使用 我还对campaign_name进行了索引,但如果在第一次匹配中使用campaign_name,聚合查询似乎会变慢,因为这不是shard key的一部分,这就是Mongo必须签入多个shard的原因 对我来说,这就是为什么查询B更快的逻辑解释。 在查询B中,Mongo将结果简化为更小的数据集,而不是将campaign_名称应用于该数据集,因此速度更快,并且不会覆盖其他碎片。MongoDB聚合管道$匹配顺序,mongodb,aggregation-framework,sharding,Mongodb,Aggregation Framework,Sharding,我有4个碎片的MongoDB集群。我的分片密钥是:{client_id:1,date:1} 使用过的集合有大约50米的文档 我将粘贴1个文档作为示例数据: { "_id" : ObjectId("54e069353e9104db470065e6"), "campaign_name" : "SC - Biker Planet", "adgroup_name" : "motociclista cerca", "client_id" :
我只是希望MongoDB能够自动计算:)A更快,因为在第一次“匹配”之后,您已经对记录进行了分组(“匹配”之后的所有结果都具有相同的“活动名称”)。在“组”中,只需计算它们
B速度较慢,因为在第一场比赛后,您有更多的结果,并且“组”中需要处理更多的数据。换句话说,脚本将计算所有找到的活动的结果。这太令人惊讶了。只要看一看,B的计算量就大得多(因为我不太了解集合中的实际文档,只知道它们的形状)。这两条管道应该总是产生相同的结果,因此如果后者更好,那么现在就使用它。如果您想检查为什么B更快,请为这两个查询发布解释。您需要将两个初始的
$match
阶段转换为查找查询并运行解释。我已经用两个解释查询链接更新了我的帖子。我认为B应该只查询1个碎片,因为碎片键是{client_id,date},但是当使用campaign_name时,它也会查询其他碎片。至少对我来说这听起来合乎逻辑。所以我认为最好的方法是在第一个$match中只使用切分键字段,然后再应用另一个$match。这是很多信息,但我看不到任何东西来解释时间上的差异。包括campaign\u name
不会让它查询到更多的碎片-它仍然可以使用client\u id
和date
以查询为目标。这是很多信息,但我看不到任何东西来解释时间上的差异。包含campaign\u name
不会使其查询比已经查询的碎片更多的碎片-它仍然可以使用client\u id
和`date>以查询为目标。
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"}
}
}])
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',
}
}])