【问题标题】:How to calculate the percentile?如何计算百分位数?
【发布时间】:2013-08-31 07:55:20
【问题描述】:

我有如下访问日志存储在 mongodb 实例中:

Time                           Service                      Latency
[27/08/2013:11:19:22 +0000]    "POST Service A HTTP/1.1"    403
[27/08/2013:11:19:24 +0000]    "POST Service B HTTP/1.1"    1022 
[27/08/2013:11:22:10 +0000]    "POST Service A HTTP/1.1"    455 

Oracle 中是否有类似PERCENTILE_DISC 的分析函数来计算百分位数?

我想计算一段时间内的延迟百分位数。

【问题讨论】:

    标签: mongodb mongodb-query percentile


    【解决方案1】:

    似乎仍然没有计算百分位数的本地方法,但通过组合几个聚合运算符,您可以获得相同的结果。

    db.items.aggregate([
            {'$group': {
                '_id': {
                    'league': '$league',
                    'base': '$base',
                    'type': '$type'
                },
                'value': {'$push': '$chaosequiv'}
            }},
            {'$unwind': '$value'},
            {'$sort': {'value': 1}},
            {'$group': {'_id': '$_id', 'value': {'$push': '$value'}}},
            {'$project': {
                '_id': 1,
                'value': {'$arrayElemAt': ['$value', {'$floor': {'$multiply': [0.25, {'$size': '$value'}]}}]}
            }}
        ], allowDiskUse=True)
    

    请注意,我在 pymongo 中编写了我的原始代码,以解决需要对第一组中的 3 个字段进行分组的问题,因此这可能比单个字段所需的更复杂。我会针对这个问题写一个解决方案,但我认为没有足够的具体信息。

    【讨论】:

    • 我知道流放之路交易工具的代码,当我看到它时。 :)
    • 先排序再分组不行吗?而不是分组、展开、排序、再次分组。
    【解决方案2】:

    Mongo 4.4 开始,$group 阶段有一个新的聚合运算符 $accumulator,允许通过 javascript 用户定义的函数在文档分组时自定义累积文档。

    因此,为了找到第 20 个百分位数:

    // { "a" : 25, "b" : 12 }
    // { "a" : 89, "b" : 73 }
    // { "a" : 25, "b" : 7  }
    // { "a" : 25, "b" : 17 }
    // { "a" : 89, "b" : 14 }
    // { "a" : 89, "b" : 17 }
    // { "a" : 25, "b" : 24 }
    // { "a" : 25, "b" : 15 }
    // { "a" : 25, "b" : 22 }
    // { "a" : 25, "b" : 94 }
    db.collection.aggregate([
      { $group: {
        _id: "$a",
        percentile: {
          $accumulator: {
            accumulateArgs: ["$b"],
            init: function() { return []; },
            accumulate: function(bs, b) { return bs.concat(b); },
            merge: function(bs1, bs2) { return bs1.concat(bs2); },
            finalize: function(bs) {
              bs.sort(function(a, b) { return a - b });
              return bs[Math.floor(bs.length*.2) + 1];
            },
            lang: "js"
          }
        }
      }}
    ])
    // { "_id" : 89, "percentile" : 17 }
    // { "_id" : 25, "percentile" : 15 }
    

    累加器:

    • 在场上积累b (accumulateArgs)
    • 初始化为空数组 (init)
    • 在数组中累积b 项(accumulatemerge
    • 最后对b项目(finalize)执行百分位数计算

    【讨论】:

      【解决方案3】:

      计算从 0 到 100 的百分位数(第 5 步)

      // { "session": 1, "date" : 2013-08-27 11:00::00, "latency" : 403 }
      // { "session": 1, "date" : 2013-08-27 11:00::01, "latency" : 1022 }
      // { "session": 1, "date" : 2013-08-27 11:00::02, "latency" : 455 }
      // { "session": 1, "date" : 2013-08-27 11:00::02, "latency" : 307 }
      // { "session": 2, "date" : 2013-08-27 12:00::00, "latency" : 403 }
      // { "session": 2, "date" : 2013-08-27 12:00::01, "latency" : 1022 }
      // { "session": 2, "date" : 2013-08-27 12:00::02, "latency" : 455 }
      // { "session": 2, "date" : 2013-08-27 12:00::02, "latency" : 307 }
      
      var interval = 5
      
      db.getCollection.aggregate([
          {
              $group:{
                  _id: { $toString: "$session" },
                  value: { $push: "$atency" }
              }
          },
          {
              $addFields:{
                  index : {$range: [0, 100, interval]}
              }
          },
          {$unwind: "$index"},
          {
              $addFields:{
                  p_index : {$divide: ["$index", 100]}
              }
          },
          {
              $addFields:{
                  percentile_x : {$toDouble: {'$arrayElemAt': ['$value', {'$floor': {'$multiply': ["$p_index", {'$size': '$value'}]}}]}}
              }
          },
          {   $project: {
                 'percentile': "$index",
                 'value': "$percentile_x"
              }
          },
              {$sort: {
                percentile: 1
              }
          }
      ])
      

      【讨论】:

        猜你喜欢
        • 2011-12-29
        • 2013-06-20
        • 2021-11-29
        • 2016-07-28
        • 2017-08-29
        • 2012-10-28
        • 2021-02-26
        • 2016-04-12
        • 2016-07-12
        相关资源
        最近更新 更多