百分位度量
让我加载一个新的数据集(汽车的数据不太适用于百分位)。我们要索引一系列网站延时数据然后运行一些百分位操作进行查看:
POST /website/logs/_bulk
{ "index": {}}
{ "latency" : 100, "zone" : "US", "timestamp" : "2014-10-28" }
{ "index": {}}
{ "latency" : 80, "zone" : "US", "timestamp" : "2014-10-29" }
{ "index": {}}
{ "latency" : 99, "zone" : "US", "timestamp" : "2014-10-29" }
{ "index": {}}
{ "latency" : 102, "zone" : "US", "timestamp" : "2014-10-28" }
{ "index": {}}
{ "latency" : 75, "zone" : "US", "timestamp" : "2014-10-28" }
{ "index": {}}
{ "latency" : 82, "zone" : "US", "timestamp" : "2014-10-29" }
{ "index": {}}
{ "latency" : 100, "zone" : "EU", "timestamp" : "2014-10-28" }
{ "index": {}}
{ "latency" : 280, "zone" : "EU", "timestamp" : "2014-10-29" }
{ "index": {}}
{ "latency" : 155, "zone" : "EU", "timestamp" : "2014-10-29" }
{ "index": {}}
{ "latency" : 623, "zone" : "EU", "timestamp" : "2014-10-28" }
{ "index": {}}
{ "latency" : 380, "zone" : "EU", "timestamp" : "2014-10-28" }
{ "index": {}}
{ "latency" : 319, "zone" : "EU", "timestamp" : "2014-10-29" }数据有三个值:延时、数据中心的区域以及时间戳。让我们对数据全集进行 百分位 操作以获得数据分布情况的直观感受:
GET /website/logs/_search
{
"size" : 0,
"aggs" : {
"load_times" : {
"percentiles" : {
"field" : "latency"
}
},
"avg_load_time" : {
"avg" : {
"field" : "latency"
}
}
}
}默认情况下,percentiles 度量会返回一组预定义的百分位数值: [1, 5, 25, 50, 75, 95, 99] 。它们表示了人们感兴趣的常用百分位数值,极端的百分位数在范围的两边,其他的一些处于中部。在返回的响应中,我们可以看到最小延时在 75ms 左右,而最大延时差不多有 600ms。与之形成对比的是,平均延时在 200ms 左右, 信息并不是很多:
...
"aggregations": {
"load_times": {
"values": {
"1.0": 75.55,
"5.0": 77.75,
"25.0": 94.75,
"50.0": 101,
"75.0": 289.75,
"95.0": 489.34999999999985,
"99.0": 596.2700000000002
}
},
"avg_load_time": {
"value": 199.58333333333334
}
}所以显然延时的分布很广,让我们看看它们是否与数据中心的地理区域有关:
GET /website/logs/_search
{
"size" : 0,
"aggs" : {
"zones" : {
// 首先根据区域我们将延时分到不同的桶中。
"terms" : {
"field" : "zone"
},
"aggs" : {
"load_times" : {
// 再计算每个区域的百分位数值。
"percentiles" : {
"field" : "latency",
// percents 参数接受了我们想返回的一组百分位数,因为我们只对长的延时感兴趣。
"percents" : [50, 95.0, 99.0]
}
},
"load_avg" : {
"avg" : {
"field" : "latency"
}
}
}
}
}
}在响应结果中,我们发现欧洲区域(EU)要比美国区域(US)慢很多,在美国区域(US),50 百分位与 99 百分位十分接近,它们都接近均值。
与之形成对比的是,欧洲区域(EU)在 50 和 99 百分位有较大区分。现在,显然可以发现是欧洲区域(EU)拉低了延时的统计信息,我们知道欧洲区域的 50% 延时都在 300ms+。
...
"aggregations": {
"zones": {
"buckets": [
{
"key": "eu",
"doc_count": 6,
"load_times": {
"values": {
"50.0": 299.5,
"95.0": 562.25,
"99.0": 610.85
}
},
"load_avg": {
"value": 309.5
}
},
{
"key": "us",
"doc_count": 6,
"load_times": {
"values": {
"50.0": 90.5,
"95.0": 101.5,
"99.0": 101.9
}
},
"load_avg": {
"value": 89.66666666666667
}
}
]
}
}
...百分位等级
这里有另外一个紧密相关的度量叫 percentile_ranks 。 percentiles 度量告诉我们落在某个百分比以下的所有文档的最小值。例如,如果 50 百分位是 119ms,那么有 50% 的文档数值都不超过 119ms。 percentile_ranks 告诉我们某个具体值属于哪个百分位。119ms 的 percentile_ranks 是在 50 百分位。 这基本是个双向关系,例如:
- 50 百分位是 119ms。
- 119ms 百分位等级是 50 百分位。 所以假设我们网站必须维持的服务等级协议(SLA)是响应时间低于 210ms。然后,开个玩笑,我们老板警告我们如果响应时间超过 800ms 会把我开除。可以理解的是,我们希望知道有多少百分比的请求可以满足 SLA 的要求(并期望至少在 800ms 以下!)。
为了做到这点,我们可以应用 percentile_ranks 度量而不是 percentiles 度量:
GET /website/logs/_search
{
"size" : 0,
"aggs" : {
"zones" : {
"terms" : {
"field" : "zone"
},
"aggs" : {
"load_times" : {
// percentile_ranks 度量接受一组我们希望分级的数值。
"percentile_ranks" : {
"field" : "latency",
"values" : [210, 800]
}
}
}
}
}
}在聚合运行后,我们能得到两个值:
"aggregations": {
"zones": {
"buckets": [
{
"key": "eu",
"doc_count": 6,
"load_times": {
"values": {
"210.0": 31.944444444444443,
"800.0": 100
}
}
},
{
"key": "us",
"doc_count": 6,
"load_times": {
"values": {
"210.0": 100,
"800.0": 100
}
}
}
]
}
}这告诉我们三点重要的信息:
- 在欧洲(EU),210ms 的百分位等级是 31.94% 。
- 在美国(US),210ms 的百分位等级是 100% 。
- 在欧洲(EU)和美国(US),800ms 的百分位等级是 100% 。
通俗的说,在欧洲区域(EU)只有 32% 的响应时间满足服务等级协议(SLA),而美国区域(US)始终满足服务等级协议的。但幸运的是,两个区域所有响应时间都在 800ms 以下,所以我们还不会被炒鱿鱼(至少目前不会)。
percentile_ranks 度量提供了与 percentiles 相同的信息,但它以不同方式呈现,如果我们对某个具体数值更关心,使用它会更方便。
参考
https://www.elastic.co/guide/cn/elasticsearch/guide/current/percentiles.html