百分位数排名聚合

编辑

一种 多值 指标聚合,用于计算从聚合文档中提取的数值的一个或多个百分位数排名。这些值可以从文档中的特定数值或 直方图字段 中提取。

请参阅 百分位数(通常)是近似值压缩执行提示,了解有关百分位数排名聚合的近似值、性能和内存使用方面的建议。

百分位数排名显示低于某个值的观测值百分比。例如,如果一个值大于或等于 95% 的观测值,则称其位于第 95 个百分位数排名。

假设您的数据由网站加载时间组成。您可能有一个服务协议,规定 95% 的页面加载在 500 毫秒内完成,99% 的页面加载在 600 毫秒内完成。

让我们看一下表示加载时间的一系列百分位数

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "field": "load_time",
                "values": [
                    500,
                    600
                ]
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          field: 'load_time',
          values: [
            500,
            600
          ]
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        field: "load_time",
        values: [500, 600],
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",   
        "values": [ 500, 600 ]
      }
    }
  }
}

字段 load_time 必须是数值字段

响应将如下所示

{
  ...

 "aggregations": {
    "load_time_ranks": {
      "values": {
        "500.0": 55.0,
        "600.0": 64.0
      }
    }
  }
}

从这些信息中,您可以确定您达到了 99% 的加载时间目标,但没有完全达到 95% 的加载时间目标

键控响应

编辑

默认情况下,keyed 标志设置为 true,将唯一的字符串键与每个存储桶关联,并将范围返回为哈希而不是数组。将 keyed 标志设置为 false 将禁用此行为

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "field": "load_time",
                "values": [
                    500,
                    600
                ],
                "keyed": False
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          field: 'load_time',
          values: [
            500,
            600
          ],
          keyed: false
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        field: "load_time",
        values: [500, 600],
        keyed: false,
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",
        "values": [ 500, 600 ],
        "keyed": false
      }
    }
  }
}

响应

{
  ...

  "aggregations": {
    "load_time_ranks": {
      "values": [
        {
          "key": 500.0,
          "value": 55.0
        },
        {
          "key": 600.0,
          "value": 64.0
        }
      ]
    }
  }
}

脚本

编辑

如果您需要针对未编制索引的值运行聚合,请使用运行时字段。例如,如果我们的加载时间以毫秒为单位,但我们希望以秒为单位计算百分位数

resp = client.search(
    index="latency",
    size=0,
    runtime_mappings={
        "load_time.seconds": {
            "type": "long",
            "script": {
                "source": "emit(doc['load_time'].value / params.timeUnit)",
                "params": {
                    "timeUnit": 1000
                }
            }
        }
    },
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "values": [
                    500,
                    600
                ],
                "field": "load_time.seconds"
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    runtime_mappings: {
      'load_time.seconds' => {
        type: 'long',
        script: {
          source: "emit(doc['load_time'].value / params.timeUnit)",
          params: {
            "timeUnit": 1000
          }
        }
      }
    },
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          values: [
            500,
            600
          ],
          field: 'load_time.seconds'
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  runtime_mappings: {
    "load_time.seconds": {
      type: "long",
      script: {
        source: "emit(doc['load_time'].value / params.timeUnit)",
        params: {
          timeUnit: 1000,
        },
      },
    },
  },
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        values: [500, 600],
        field: "load_time.seconds",
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "runtime_mappings": {
    "load_time.seconds": {
      "type": "long",
      "script": {
        "source": "emit(doc['load_time'].value / params.timeUnit)",
        "params": {
          "timeUnit": 1000
        }
      }
    }
  },
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "values": [ 500, 600 ],
        "field": "load_time.seconds"
      }
    }
  }
}

HDR 直方图

编辑

HDR 直方图(高动态范围直方图)是一种替代实现,在计算延迟测量的百分位数排名时非常有用,因为它比 t-digest 实现更快,但代价是更大的内存占用。此实现保持固定的最坏情况百分比误差(指定为有效数字)。这意味着,如果在一个设置为 3 个有效数字的直方图中记录从 1 微秒到 1 小时(3,600,000,000 微秒)的值,它将为高达 1 毫秒的值保持 1 微秒的值分辨率,为最大跟踪值(1 小时)保持 3.6 秒(或更好)的值分辨率。

可以通过在请求中指定 hdr 对象来使用 HDR 直方图

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "field": "load_time",
                "values": [
                    500,
                    600
                ],
                "hdr": {
                    "number_of_significant_value_digits": 3
                }
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          field: 'load_time',
          values: [
            500,
            600
          ],
          hdr: {
            number_of_significant_value_digits: 3
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        field: "load_time",
        values: [500, 600],
        hdr: {
          number_of_significant_value_digits: 3,
        },
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",
        "values": [ 500, 600 ],
        "hdr": {                                  
          "number_of_significant_value_digits": 3 
        }
      }
    }
  }
}

hdr 对象指示应使用 HDR 直方图来计算百分位数,并且可以在对象内部指定此算法的特定设置

number_of_significant_value_digits 指定直方图的值分辨率,以有效数字表示

HDR 直方图仅支持正值,如果传递负值,则会报错。如果值的范围未知,也不建议使用 HDR 直方图,因为这可能会导致高内存使用率。

缺失值

编辑

missing 参数定义应如何处理缺少值的文档。默认情况下,它们将被忽略,但也可以将它们视为具有值。

resp = client.search(
    index="latency",
    size=0,
    aggs={
        "load_time_ranks": {
            "percentile_ranks": {
                "field": "load_time",
                "values": [
                    500,
                    600
                ],
                "missing": 10
            }
        }
    },
)
print(resp)
response = client.search(
  index: 'latency',
  body: {
    size: 0,
    aggregations: {
      load_time_ranks: {
        percentile_ranks: {
          field: 'load_time',
          values: [
            500,
            600
          ],
          missing: 10
        }
      }
    }
  }
)
puts response
const response = await client.search({
  index: "latency",
  size: 0,
  aggs: {
    load_time_ranks: {
      percentile_ranks: {
        field: "load_time",
        values: [500, 600],
        missing: 10,
      },
    },
  },
});
console.log(response);
GET latency/_search
{
  "size": 0,
  "aggs": {
    "load_time_ranks": {
      "percentile_ranks": {
        "field": "load_time",
        "values": [ 500, 600 ],
        "missing": 10           
      }
    }
  }
}

load_time 字段中没有值的文档将与具有值 10 的文档落在同一个存储桶中。