随着时间的推移范围支持分桶分析

2023-12-20

Read this https://www.compose.com/articles/first-steps-of-an-analytics-platform-with-mongodb/,并尝试进行实验。

下面是我的架构。

SCHEMA:

{
    "s"  : "CB",
    "c"  : "REQ_RCV",
    "e"  : "sms_click",
    "st" : "i",
    "b"  : "2",
    "a"  : "1",
    "u"  : "b1_h1_d1_m1_user_2",
    "c#" : "b1_h1_d1_m1_cr-2",
    "@"  : ISODate("2016-10-01T06:03:00.000Z"), //Indexed
    "@h" : "16100106", //hourly bucket
    "@d" : "161001",                            //Indexed
    "@m" : "1610"
}

以下是解释计划:

> 2017-01-22T13:43:47.764+0530 I COMMAND  [conn34] command test-analytics.template3 appName: "MongoDB Shell" command: aggregate {
> aggregate: "template3", pipeline: [ { $match: { @: { $gte: new
> Date(1483228800000), $lte: new Date(1483315199000) } } }, { $group: {
> _id: { b: "$b", HOURLY: "$@h", s: "$s" }, count: { $sum: 1.0 } } }, { $project: { _id: 0.0, BUCKET: "$_id.b", SERVICE: "$_id.s", TIME:
> "$_id.HOURLY", count: 1.0 } }, { $sort: { SERVICE: 1.0, BUCKET: 1.0,
> TIME: 1.0 } } ], cursor: {} } planSummary: IXSCAN { @: 1.0 }
> keysExamined:106888 docsExamined:106888 hasSortStage:1
> cursorExhausted:1 numYields:925 nreturned:96 reslen:7095 locks:{
> Global: { acquireCount: { r: 1860 } }, Database: { acquireCount: { r:
> 930 } }, Collection: { acquireCount: { r: 929 } } }
> protocol:op_command **3499ms**


> 2017-01-22T13:44:24.825+0530 I COMMAND  [conn34] command test-analytics.template3 appName: "MongoDB Shell" command: aggregate {
> aggregate: "template3", pipeline: [ { $match: { @d: "170101" } }, {
> $group: { _id: { b: "$b", HOURLY: "$@h", s: "$s" }, count: { $sum: 1.0
> } } }, { $project: { _id: 0.0, BUCKET: "$_id.b", SERVICE: "$_id.s",
> TIME: "$_id.HOURLY", count: 1.0 } }, { $sort: { SERVICE: 1.0, BUCKET:
> 1.0, TIME: 1.0 } } ], cursor: {} } planSummary: IXSCAN { @d: 1.0 } keysExamined:106888 docsExamined:106888 hasSortStage:1
> cursorExhausted:1 numYields:865 nreturned:96 reslen:7095 locks:{
> Global: { acquireCount: { r: 1740 } }, Database: { acquireCount: { r:
> 870 } }, Collection: { acquireCount: { r: 869 } } }
> protocol:op_command **1294ms**

问题:

  1. 尽管这两个查询都检查了相同数量的文档 为什么输出有时间差?
  2. Are $lte, $gte运算符仅在日期范围上变慢,甚至在数字比较上也变慢?
  3. 由于分桶可以提供更快的响应,那么如何使用分桶进行范围查询?我可以进行多个聚合时间桶调用来支持范围查询,但这会增加往返时间,有什么建议吗?
  4. 是否可以使用$and两个人$match在聚合查询中支持范围存储?目前聚合接受多个$match但第一个输出$match被赋予第二个$match,但我想要的是添加/分组个人$match结果到下一个管道。

第四季度的可能答案:

db.template3.aggregate([ 
    {
        $match: {
            $or: [
                {"@d":"170301"},
                {"@d":"170306"}, 
                {"@d":"170202"}, 
                {"@d":"170303"},
                {"@d":"170304"}, 
                {"@d":"170305"}
            ]
        }
    },
    { $project: { _id: 0, "b": 1, "s": 1, "@h": 1 } }, 
    {
        $group: {
            _id: {"b": "$b", "HOURLY": "$@h", "s": "$s" }, 
            count: { $sum: 1 } 
        }
    },  
    { 
        $project: {
            _id: 0, 
            "BUCKET": "$_id.b",
            "SERVICE": "$_id.s",
            "TIME": "$_id.HOURLY", 
            count: 1
        }
    },         
    { $sort: { "SERVICE": 1, "BUCKET": 1, "TIME": 1 } } 
]);

在这个答案中,我们可以使用桶的混合(每日和每月),但这仍然会使用它自己的索引。读https://docs.mongodb.com/manual/reference/operator/query/or/#or-clauses-and-indexes https://docs.mongodb.com/manual/reference/operator/query/or/#or-clauses-and-indexes.

示例查询:

db.template3.aggregate([ 

    {$match:{"@h":{$gte : 17020511, $lte : 17030511}, "st":"i"}}, 

    {$project : {"_id":0,  "@h":1,"c":1, "@m":1}}, 

    {$group:{_id:{ "HOURLY":"$@h", "c":"$c"}, count:{$sum:1}}},

    {$project : {_id:0, "COUNTER":"$_id.c","TIME":"$_id.HOURLY", count:1}}, 

    {$sort:{"COUNTER":1,"TIME":1}}
]);

Output:

{ "count" : 2255, "COUNTER" : "REQ_RCVD", "TIME" : 17020511 }
{ "count" : 28888, "COUNTER" : "REQ_RCVD", "TIME" : 17020600 }
{ "count" : 37613, "COUNTER" : "REQ_RCVD", "TIME" : 17020601 }
{ "count" : 6723, "COUNTER" : "REQ_RCVD", "TIME" : 17020602 }
{ "count" : 14057, "COUNTER" : "REQ_RCVD", "TIME" : 17020603 }
{ "count" : 12405, "COUNTER" : "REQ_RCVD", "TIME" : 17020604 }
{ "count" : 2392, "COUNTER" : "REQ_RCVD", "TIME" : 17020611 }
{ "count" : 28784, "COUNTER" : "REQ_RCVD", "TIME" : 17020700 }
{ "count" : 37494, "COUNTER" : "REQ_RCVD", "TIME" : 17020701 }
{ "count" : 6697, "COUNTER" : "REQ_RCVD", "TIME" : 17020702 }
{ "count" : 13930, "COUNTER" : "REQ_RCVD", "TIME" : 17020703 }
{ "count" : 12493, "COUNTER" : "REQ_RCVD", "TIME" : 17020704 }
{ "count" : 2225, "COUNTER" : "REQ_RCVD", "TIME" : 17020711 }
{ "count" : 28821, "COUNTER" : "REQ_RCVD", "TIME" : 17020800 }
{ "count" : 37949, "COUNTER" : "REQ_RCVD", "TIME" : 17020801 }
{ "count" : 6676, "COUNTER" : "REQ_RCVD", "TIME" : 17020802 }
{ "count" : 14039, "COUNTER" : "REQ_RCVD", "TIME" : 17020803 }
{ "count" : 12349, "COUNTER" : "REQ_RCVD", "TIME" : 17020804 }
{ "count" : 2332, "COUNTER" : "REQ_RCVD", "TIME" : 17020811 }
{ "count" : 28379, "COUNTER" : "REQ_RCVD", "TIME" : 17020900 }

优化

  1. 我觉得由于读取非索引字段而花费了更多时间。 因此docsExamined: 106888

  2. 当我使用时有一定的改进$project before $group

  3. 我变了"@h"数据类型来自String to Integer (NumberInt),我认为它会进一步改进。


让我们一一解答您的问题:

尽管两个查询检查了相同数量的文档,为什么输出存在时间差异?

仅从单个执行中查看性能指标实际上并不是它的工作原理。在得出结论之前,您应该取几次执行的平均值,因为有几个因素在起作用。 话虽这么说,MongoDB 将最常用的文档缓存在内存中并将其保留在那里,除非它必须为其他文档腾出内存。因此,如果查询访问已从先前查询中缓存的文档,它应该会更快。

另外,在 MongoDB 中,聚合仅在开头使用索引(如果有)。例如$match and $sort阶段可以使用索引。在你的情况下$match是第一个管道阶段,所以这是一个胜利。

$lte, $gte 仅在日期范围上很慢,还是在数字比较上也很慢..?

在 MongoDB 中,数据存储在BSON http://bsonspec.org/, so 日期基本上是数字 https://docs.mongodb.com/manual/reference/bson-types/#date当他们进行比较时。所以没有区别。

既然分桶可以提供更快的响应,那么如何使用分桶进行范围查询呢?我可以进行多个聚合时间桶调用来支持范围查询,但这会增加往返时间,有什么建议吗?

虽然我还没有测试过它,但我真的怀疑 time_bucket 方法能否提供更快的响应。自从created_at总是会增加,在这种情况下,索引也会被附加到没有 time_bucket 的末尾。此外,在数组上创建的索引大小比在简单日期字段上创建的索引大小相对较大。这不会导致在 RAM 中安装索引的问题吗?

当您在匹配之前在日期字段上使用某些函数时,使用 time_bucket 是有意义的。如果在匹配之前只从日期字段中提取年份,则会使日期上的现有索引变得无用。

最好将参数转换为与数据库中的数据类型匹配,而不是相反。

那可能吗$and of two $match在聚合查询中以支持范围存储。目前聚合接受多个$match但 $match 的第一个输出被赋予第二个 $match,但我想要的是添加/分组个人$match结果到下一个管道。

是的,这是可能的。如果它是$and,您只需在中指定用逗号分隔的所有过滤器$match阶段。其$or使用$or https://docs.mongodb.com/manual/reference/operator/query/or/操作员。

如果你有two $macthMongoDB 将其一一结合为一 https://docs.mongodb.com/manual/core/aggregation-pipeline-optimization/#match-match-coalescence。因此您无需担心添加多个比赛阶段的结果。

现在你的优化 Points

我觉得由于读取非索引字段而花费了更多时间。因此 docsExamined:106888

Yes, 涵盖查询 https://docs.mongodb.com/manual/core/query-optimization/#covered-query速度更快。

当我在 $group 之前使用 $project 时有一些改进

如果文档的大小减小$group阶段通过使用$project,那么是的,这是真的。

我变了@hdataType从string改为int(NumberInt),我想还会再改进一些。

这不一定是真的,但普遍情况是这样。你可以检查一下这个答案 https://stackoverflow.com/a/16504625/2965883.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

随着时间的推移范围支持分桶分析 的相关文章

随机推荐