在大数据分析中,对数据进行计数去重是比较常见的需求,而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
综合上述分析,DataSketches 和HyperUnique的聚合效率要比cardinality的高,两者在ingestion 阶段就做了相关优化,cardinality的效率较前两者较低,但这三者的结果都为小数,为估算值,druid-distinctCount的聚合结果为整数,但是存在较多限制,并且在大数据量的效率如何还需验证。