druid.io 去重计数

   在大数据分析中,对数据进行计数去重是比较常见的需求,而druid.io中提供了多种去重计数的aggregtions函数,对于这些去重的aggregtions也不尽相同。druid中提供的去重aggregation如下:

   1、DataSketches aggregtions :

    yahoo提供的分析包,此算法也是采用最大估计的算法,在数据摄入阶段(ingestion time),druid会存储sketch 相关数据,在query查询阶段,查询效率也可以更快,此hyperloglog准确一些,速度也快一点。

   简单配置说明:  

"metricsSpec": [
         {
          "name" : "count",
          "type" : "count"
         },
         {
         "name":"sketch_deviceid",
         "type":"thetaSketch",
          "fieldName":"deviceid",
         "isInputThetaSketch":"false",
         "size":"16384"
          }
       ],

   query阶段:

"aggregations": [
    {
       "type": "longSum",
       "name": "count",
       "fieldName": "count"
    },
    {
       "type"  : "thetaSketch",
       "name": "sketch_success",
       "fieldName"  : "sketch_deviceid"
    }        
]

官方参考文档:http://druid.io/docs/latest/development/extensions-core/datasketches-aggregators.html

   2、HyperUnique aggregtions:   

       利用HyperLogLog计算估计值,结果为小数,但需要在indexing time阶段加入“hyperUnique” metric 以支持此aggregation。在摄入阶段进行优化,比Cardinality aggregtions聚合效率要高。

官方参考文档: http://druid.io/docs/latest/querying/aggregations

   3、Cardinality aggregtions : 

  基于HyperLogLog算法,只在查询阶段做了优化,不能减少存储容量,基数大时,效率可能会有问题。

由于在metabase 中对druid数据源采用的是Cardinality aggregtions,所以重点研究了一下。

首先Cardinality aggregtions结果返回值也为估算值小数,在metabase中对于Cardinality 的postaggregation是错误的,是个bug,对于cardinality和hyperUnique的聚合, post-aggregator type 的类型为“finalizingFieldAccess”,而非“fieldAccess”,采用fieldAccess type的话,查询会报 java.lang.ClassCastException 。正确的写法如下:

{ "queryType":"timeseries",
  "dataSource": "out-tvs-timeon.behavior",
  "granularity":{"type":"period","period":"P1D","timeZone":"UTC"},
  "context":{"timeout":60000,"queryId":"2f8cd622-0aca-48a7-8945-f21f869a2886"} ,
  "descending": "true",
  "aggregations": [
    { "type": "count", "name": "___COUNT_209" },
    { "type": "cardinality", "name": "___DISTINCT_210", "fields": ["session_id"],"round":"true" }
  ],
  "postAggregations": [
    { "type": "arithmetic",
      "name": "sample_divide",
      "fn": "/",
      "fields": [
        { "type": "fieldAccess","name":"___COUNT_2091","fieldName": "___COUNT_209" },
        { "type": "finalizingFieldAccess","name":"___DISTINCT_2101","fieldName": "___DISTINCT_210"}
      ]
   }],
 "intervals": ["2018-07-22T00:00:00.000Z/2018-08-23T00:00:00.000Z"]
}

    注意并且当在druid的0.10版本中,上述查询会出现“finalizingFieldAccess not recoginez”,此错误为druid的0.10版本的bug,将druid的版本升级至0.12版本即可。

  类似,druid已支持简单的SQL查询,但在0.10上不支持,需升级druid至0.12

  4、druid-distinctCount:

     第三方community extensions包,结果为整数。效率还未大数据量测试。

     首先需要到maven仓库下载对应druid版本的jar,并druid中的extensions目录下,并建立druid-distinctcount,将jar复制到目录下,并在druid 的common.runtime.properties中添加此extension的配置

druid.extensions.loadList=["mysql-metadata-storage", "druid-hdfs-storage","druid-kafka-indexing-service","kafka-emitter","druid-datasketches","druid-distinctcount"]

   重启druid即可。

但是distinctCount 存在较大的误差,有时候会出现错误,其具有较多限制,也不适合生产环境使用。具体可参照官网

http://druid.io/docs/latest/development/extensions-contrib/distinctcount.html

算法比较:    

去重计数聚合函数 cardinality aggregator HyperLogLog   1、RSE标准差: 1.04/sqrt(m)
m  an auxiliary memory of m units (typically, “short bytes”)
2、e.g:10^9 with a typical accuracy of 2% while using a memory of only 1.5 kilobytes
1:datasketches的基数运算比HyperLogLog丰富:支持集合的交、并、补运算。
2:datasketches使用扩展插件实现,HyperUnique为内置功能。
3:datasketches精度高于HyperLoglog,并且可以进行灵活的参数调整。
1、此聚合函数比hyperUnique aggregator要慢,官方建立此采用hyperUnique aggregator
2、提供了round配置可提供数值型,但经测试round不起作用
3、druid未提供关于调优参数 m的参数配置
4、只在查询阶段进行优化
HyperUnique aggregator HyperLogLog  1:在druid接入时,需添加“hyperUnique” metric
{
  "type" : "hyperUnique",
  "name" : ,
  "fieldName" : ,
  "isInputHyperUnique" : false,
  "round" : false
}
2:数据druid接入和查询均做了优化
DataSketches aggregator datasketches 1、RSE标准差:  < 1/√ k - 1  sketch size of k   
Thus, the confidence level (the fractional area) between +1 RSE (+1 SD) and -1 RSE (-1 SD) is 68.27%. Similarly, the confidence level between +2 RSE (+2 SD) and -2 RSE (-2 SD) is 95.4%
2、参考文档:https://datasketches.github.io/docs/Theta/ThetaAccuracy.html 
1:在druid接入时,需添加添加“thetaSketch”
 {
          "type":"thetaSketch",
          "name":"theta_pdid",
          "fieldName":"pdid"
        }
2:数据druid接入和查询均做了优化
3:可灵活调精度参数
DistinctCount aggregator 未知     前提:
1:必须保证相同某个dimension的值存储到相同的segments中。
2:必须保证queryGranularity 能被segmentGranularity 整除
限制:
1:groupBy  keys的数量不能超过 maxIntermediateRows  ,否则结果错误
2:当用到topN时,numValuesPerPass 不能太大,否则会内存溢出。
测试结论:
采用thetaSketch,并根据实际数据进行参数的调整优化以达到较高精度
1、datasketches 对空不计数,HyperLogLog则对空计数
2、datasketch返回为整数,HyperLogLog返回为15小数。
3、datasketch可调整参数提高计数精度,而HyperLogLog未提供参数优化
  维度 结果 误差
{ "queryType":"timeseries",
  "dataSource": "out_timeon_behavior_merge_t",
 "intervals": ["2018-10-09T00:00:00.000Z/2018-10-09T09:00:00.000Z"]
}
thetaSketch: size: 16384
page_session groupby :342  
cardinality:344.40075465357125      2.4
thetaSketch:342.0                                0
pdid groupby  : 1407  
cardinality: 1401.6440668974283    7.4 7.4
thetaSketch:1407.0               0
session_id groupby  : 1439  
cardinality: 1405.613060387714      34
thetaSketch:1438                                 1,其中有一个session_id为空
page_id groupby  : 30969  
cardinality: 31643.23982223063       674       2%
thetaSketch:30798.883625510232    171  0.5%
{ "queryType":"timeseries",
  "dataSource": "out_timeon_behavior_merge_t",
 "intervals": ["2018-10-09T00:00:00.000Z/2018-10-09T09:00:00.000Z"]
}
thetaSketch: size: 16384*2
page_id groupby  : 30969  
cardinality: 31643.23982223063       674       2%
thetaSketch:30969.0 0   0%

      综合上述分析,DataSketches 和HyperUnique的聚合效率要比cardinality的高,两者在ingestion 阶段就做了相关优化,druid并提供了DataSketches 参数调整的参数,可通过调参来调整算法的准确度,cardinality的效率较前两者较低,误差与HyperUnique一样,大约在2%左右,druid-distinctCount的聚合结果为整数,但是存在较多限制和误差的问题,不易采用,并且在大数据量的效率如何还需验证。DataSketches为最优选择。

  

你可能感兴趣的:(druid,druid)