ElasticSearch Aggregation 之 percentiles

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: ES百分比聚合

首先简单介绍下百分位数,我们称位于 n% 位置的值称为第 n 百分位数。在不同的应用程序中百分位的计算方式会有略微的差异,但不影响我们对百分位数的应用,比如找出数据中异常等。比如:Excel、Mysql,Es等。这里我们介绍两种百分位的计算方法。

1、百分位计算方法

image.png

1)计算方式一

  • 将一组数据 data 从小到大排序(该数据的数量为m)
  • 计算第 n 百分位数所在位置 p :p = 1 + (m - 1) * n%
  • 计算第 n 百分位数的值 x,得到位置 p 所在数据组中的数据左右相邻的数值 data[p-1] 和 data[p+1] ,则 x = data[p-1] + (data[p+1] - data[p-1])*(p - p向下取整的整数)。


以上图的数据为例,计算第80位百分数:


  • 计算位置:p = 1 + (12 -1)*0.8 = 9.8
  • 计算值:x = 8999.65 + (9759.25 - 8999.65) * (9.8 - 9) = 9607.330

2)计算方式二

  • 将一组数据 data 从小到大排序(该数据的数量为m)
  • 计算第 n 百分位数所在位置 p : p = (m - 1) * n% = a(整数) + b(小数)
  • 计算第 n 百分位数的值 x,x = data[a+1] * (1 - b) + data[a+2] * b


以上图的数据为例,计算第80位百分数:


  • 计算位置:p = (12 - 1)* 0.8 = 8.8 = 8 + 0.8
  • 计算值:x = 8999.65 * (1 - 0.8) + 9759.25 * 0.8 = 9607.330

2、Percentiles

ES 的百分比聚合可以从文档中数值类型的字段中提取一个或多个百分位数,默认情况下会按照 [ 1, 5, 25, 50, 75, 95, 99 ] 进行返回。


1)基础用法


{
  "aggs" : {
        "{percentiles_name}" : {
            "percentiles" : {
                "field" : "{percentiles_field_name}" ,
                "percents" : "[{percent1},{percent2},...]",
                "keyed" : "{true/false}"
            }
        }
    }
}


percentiles_name 自定义 percentiles 的名称

  • percentiles_field_name 参与计算的字段名
  • percents 指定返回的百分比数值
  • keyed 返回格式按照{key:value}的方式返回,而非数组 {key:xxx,value:xxx} ,默认为true


获取产品销售价格的百分数:


POST /order/_search?size=0
{
  "aggs" : {
        "price_percentiles" : {
            "percentiles" : {
                "field" : "price" 
            }
        }
    }
}


返回结果:


{
  ...
  "aggregations" : {
    "price_percentiles" : {
      "values" : {
        "1.0" : 100.0,
        "5.0" : 100.0,
        "25.0" : 3974.73,
        "50.0" : 8176.825000000001,
        "75.0" : 9379.45,
        "95.0" : 9996.914,
        "99.0" : 9999.2
      }
    }
  }
}



获取产品销售价格的百分数,并指定百分数 [10,80,90] :


POST /order/_search?size=0
{
  "aggs" : {
        "price_percentiles" : {
            "percentiles" : {
                "field" : "price" ,
                "percents" : [10, 80, 90]
            }
        }
    }
}



返回结果:


{
  ...
  "aggregations" : {
    "price_percentiles" : {
      "values" : {
        "10.0" : 100.0,
        "80.0" : 9780.959,
        "90.0" : 9983.198
      }
    }
  }
}



使用数组方式返回结果:


POST /order/_search?size=0
{
  "aggs" : {
        "price_percentiles" : {
            "percentiles" : {
                "field" : "price" ,
                "percents" : [10, 80, 90],
                "keyed": false
            }
        }
    }
}



返回结果:


{
  ...
  "aggregations" : {
    "price_percentiles" : {
      "values" : [
        {
          "key" : 10.0,
          "value" : 100.0
        },
        {
          "key" : 80.0,
          "value" : 9780.959
        },
        {
          "key" : 90.0,
          "value" : 9983.198
        }
      ]
    }
  }
}



2)缺失值


默认情况下,当文档中缺失计算字段值时,该文档将会被忽略,若我们希望使用这部分文档,可以通过设置 missing 参数。以下例子中,缺失字段的 price 将按照 0 来计算。


POST /order/_search?size=0
{
  "aggs" : {
        "price_percentiles" : {
            "percentiles" : {
                "field" : "price" ,
        "missing" : 0
            }
        }
    }
}



3)精确度


百分位度量使用 TDigest 近似算法来计算,该算法具有以下几个特性:


  • 百分位的准确度与百分位的位置极端程度成正比,也就是位于始末的1 或 99 的百分位要比中间位置的要更准确
  • 数据集越小,百分位数的准确度越高;当数据集较小时,可达到100%准确
  • 随着数据集的增长,算法开始对百分位进行估算。根据聚合数据的分布及数据量的大小,可以有效的在准确度和节省内存之间作出权衡


需要注意的是,在实时性、精确度、数据量三个特性中,我们最多只能满足两个,而近似算法选择了实时性和大数据量,所以会损失一定的精确度,提供相对准确的分析结果。


4)压缩


压缩参数 compression 可以帮助近似算法(tdigest)平衡内存的使用和精度的估算。


POST /order/_search?size=0
{
  "aggs" : {
        "price_percentiles" : {
            "percentiles" : {
                "field" : "price" ,
        "tdigest": {
                  "compression": 200    
                }
            }
        }
    }
}



TDigest 算法使用多个节点来执行百分位的计算,使用的节点越多,占用的内存越大,计算的结果越精确。设置该参数后,节点数量限制为最多 20 * compression,默认值为100,也就是 20 * 100 = 2000 个节点。每个节点大约占用32字节的内存,那么在最糟糕的情况下(大量的数据依次到达) 2000个节点就占用 64KB。实际上,数据往往更随机,而 TDigest 将使用更少的内存。



5)HDR 直方图


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


GET /order/_search?size=0
{
  "size": 0,
  "aggs": {
    "price_percentiles": {
      "percentiles": {
        "field": "price",
        "percents": [ 95, 99, 99.9 ],
        "hdr": {                                  
          "number_of_significant_value_digits": 3 
        }
      }
    }
  }
}



  • hdr 指定直方图相关的参数
  • number_of_significant_value_digits 指定以有效位数为单位的直方图值的分辨率



注意:hdr直方图只支持正值,如果传递负值,则会出错。如果值的范围是未知的,那么使用HDRHistogram也不是一个好主意,因为这可能会导致内存的大量使用。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
索引 存储 SQL
ElasticSearch Aggregations 分析
这篇文章重点分析让ES步入数据分析领域的Aggregation相关的功能和设计。
2966 0
|
16天前
|
数据可视化 索引
elasticsearch head、kibana 安装和使用
elasticsearch head、kibana 安装和使用
|
28天前
|
存储 负载均衡 索引
linux7安装elasticsearch-7.4.0集群配置
linux7安装elasticsearch-7.4.0集群配置
113 0
|
2月前
|
存储 监控 搜索推荐
在生产环境中部署Elasticsearch:最佳实践和故障排除技巧——安装篇(一)
在生产环境中部署Elasticsearch:最佳实践和故障排除技巧——安装篇(一)
|
4月前
ElasticSearch-Head浏览器插件离线安装
ElasticSearch-Head浏览器插件离线安装
91 0
|
15天前
|
JSON Unix Linux
Elasticsearch如何安装
Elasticsearch如何安装
|
3月前
|
前端开发 安全 Ubuntu
Elasticsearch安装和配置
Elasticsearch安装和配置
116 0

热门文章

最新文章