跳转到主要内容

聚合

信息

Apache Druid 支持两种查询语言:Druid SQL原生查询。本文档描述原生语言。有关 SQL 中可用聚合器的信息,请参阅 SQL 文档

您可以使用聚合:

  • 在摄取规范中,以便在数据进入 Apache Druid 之前对其进行汇总。
  • 在查询时,以便汇总结果数据。

以下部分列出了可用的聚合函数。除非另有说明,聚合均可在摄取时和查询时使用。

精确聚合

Count 聚合器

count 计算与过滤器匹配的 Druid 行数。

属性描述是否必须
type必须为 "count"。
name聚合器的输出名称

示例

{ "type" : "count", "name" : "count" }

count 聚合器计算的是 Druid 的行数,这并不总是等于摄取的原始事件数量。这是因为 Druid 可以配置为在摄取时进行汇总(Rollup)。要计算摄取的原始数据行数,请在摄取时包含一个 count 聚合器,并在查询时使用 longSum 聚合器。

Sum 聚合器

属性描述是否必须
type必须为 "longSum"、"doubleSum" 或 "floatSum"。
name求和值的输出名称。
fieldName要进行求和的输入列名。否。您必须指定 fieldNameexpression
expression您可以指定一个内联 表达式 作为 fieldName 的替代方案。否。您必须指定 fieldNameexpression

longSum 聚合器

将值的总和计算为 64 位有符号整数。

示例

{ "type" : "longSum", "name" : "sumLong", "fieldName" : "aLong" }

doubleSum 聚合器

将值的总和计算并存储为 64 位浮点值。类似于 longSum

示例

{ "type" : "doubleSum", "name" : "sumDouble", "fieldName" : "aDouble" }

floatSum 聚合器

将值的总和计算并存储为 32 位浮点值。类似于 longSumdoubleSum

示例

{ "type" : "floatSum", "name" : "sumFloat", "fieldName" : "aFloat" }

Min 和 max 聚合器

属性描述是否必须
type必须为 "doubleMin"、"doubleMax"、"floatMin"、"floatMax"、"longMin" 或 "longMax"。
name最小值或最大值的输出名称。
fieldName要计算最小值或最大值的输入列名。否。您必须指定 fieldNameexpression
expression您可以指定一个内联 表达式 作为 fieldName 的替代方案。否。您必须指定 fieldNameexpression

doubleMin 聚合器

doubleMin 计算所有输入值和 null 的最小值。

示例

{ "type" : "doubleMin", "name" : "maxDouble", "fieldName" : "aDouble" }

doubleMax 聚合器

doubleMax 计算所有输入值和 null 的最大值。

示例

{ "type" : "doubleMax", "name" : "minDouble", "fieldName" : "aDouble" }

floatMin 聚合器

floatMin 计算所有输入值和 null 的最小值。

示例

{ "type" : "floatMin", "name" : "minFloat", "fieldName" : "aFloat" }

floatMax 聚合器

floatMax 计算所有输入值和 null 的最大值。

示例

{ "type" : "floatMax", "name" : "maxFloat", "fieldName" : "aFloat" }

longMin 聚合器

longMin 计算所有输入值和 null 的最小值。

示例

{ "type" : "longMin", "name" : "minLong", "fieldName" : "aLong" }

longMax 聚合器

longMax 计算所有指标值和 null 的最大值。

示例

{ "type" : "longMax", "name" : "maxLong", "fieldName" : "aLong" }

doubleMean 聚合器

计算并返回列值的算术平均值,结果为 64 位浮点值。

属性描述是否必须
type必须为 "doubleMean"。
name平均值的输出名称。
fieldName要计算算术平均值的输入列名。

示例

{ "type" : "doubleMean", "name" : "aMean", "fieldName" : "aDouble" }

doubleMean 仅限查询时使用。它不适用于索引(摄取)阶段。若要在摄取时实现平均值聚合,请参考 DataSketches 扩展中的 分位数 (Quantiles) 聚合器

First 和 last 聚合器

First 和 last 聚合器确定时间列最早和最新值对应的指标值。

在启用了汇总(rollup)的段(segment)上使用 first 或 last 聚合器的查询,返回的是汇总后的值,而不是原始摄取数据中的第一个或最后一个值。在这种情况下,timeColumn 将被忽略,聚合将使用段创建时存储的原始时间列值。

数值型 first 和 last 聚合器
属性描述是否必须
type必须为 "doubleFirst"、"doubleLast"、"floatFirst"、"floatLast"、"longFirst"、"longLast"。
name第一个或最后一个值的输出名称。
fieldName要计算第一个或最后一个值的输入列名。
timeColumn用于时间值的输入列名。必须是 LONG 类型列。否。默认为 __time

doubleFirst 聚合器

doubleFirst 计算时间列最小值对应的输入值;如果不存在对应行,默认模式返回 0,SQL 兼容模式返回 null

示例

{
"type" : "doubleFirst",
"name" : "firstDouble",
"fieldName" : "aDouble"
}
doubleLast 聚合器

doubleLast 计算时间列最大值对应的输入值;如果不存在对应行,默认模式返回 0,SQL 兼容模式返回 null

示例

{
"type" : "doubleLast",
"name" : "lastDouble",
"fieldName" : "aDouble",
"timeColumn" : "longTime"
}
floatFirst 聚合器

floatFirst 计算时间列最小值对应的输入值;如果不存在对应行,默认模式返回 0,SQL 兼容模式返回 null

示例

{
"type" : "floatFirst",
"name" : "firstFloat",
"fieldName" : "aFloat"
}
floatLast 聚合器

floatLast 计算时间列最大值对应的指标值;如果不存在对应行,默认模式返回 0,SQL 兼容模式返回 null

示例

{
"type" : "floatLast",
"name" : "lastFloat",
"fieldName" : "aFloat"
}
longFirst 聚合器

longFirst 计算时间列最小值对应的指标值;如果不存在对应行,默认模式返回 0,SQL 兼容模式返回 null

示例

{
"type" : "longFirst",
"name" : "firstLong",
"fieldName" : "aLong"
}
longLast 聚合器

longLast 计算时间列最大值对应的指标值;如果不存在对应行,默认模式返回 0,SQL 兼容模式返回 null

示例

{
"type" : "longLast",
"name" : "lastLong",
"fieldName" : "aLong",
"timeColumn" : "longTime"
}

字符串型 first 和 last 聚合器
属性描述是否必须
type必须为 "stringFirst"、"stringLast"。
name第一个或最后一个值的输出名称。
fieldName要计算第一个或最后一个值的输入列名。
timeColumn用于时间值的输入列名。必须是 LONG 类型列。否。默认为 __time
maxStringBytes计算每组的第一个或最后一个值时,要累积的字符串值的最大大小。超过此长度的值将被截断。否。默认为 1024。

stringFirst 聚合器

stringFirst 计算时间列最小值对应的指标值;如果不存在对应行,返回 null

示例

{
"type" : "stringFirst",
"name" : "firstString",
"fieldName" : "aString",
"maxStringBytes" : 2048,
"timeColumn" : "longTime"
}

stringLast 聚合器

stringLast 计算时间列最大值对应的指标值;如果不存在对应行,返回 null

示例

{
"type" : "stringLast",
"name" : "lastString",
"fieldName" : "aString"
}

ANY 聚合器

(Double/Float/Long/String) ANY 聚合器不能用于摄取规范中,只能作为查询的一部分指定。

返回任意值(包括 null)。此聚合器通过返回遇到的第一个值(包括 null)来简化并优化性能。

数值型 any 聚合器
属性描述是否必须
type必须为 "doubleAny"、"floatAny" 或 "longAny"。
name值的输出名称。
fieldName要计算值的输入列名。

doubleAny 聚合器

doubleAny 返回任意 double 型指标值。

示例

{
"type" : "doubleAny",
"name" : "anyDouble",
"fieldName" : "aDouble"
}
floatAny 聚合器

floatAny 返回任意 float 型指标值。

示例

{
"type" : "floatAny",
"name" : "anyFloat",
"fieldName" : "aFloat"
}
longAny 聚合器

longAny 返回任意 long 型指标值。

示例

{
"type" : "longAny",
"name" : "anyLong",
"fieldName" : "aLong"
}

stringAny 聚合器

stringAny 返回输入中存在的任意字符串值。

属性描述是否必须
type必须为 "stringAny"。
name值的输出名称。
fieldName要计算值的输入列名。
maxStringBytes计算每组的第一个或最后一个值时,要累积的字符串值的最大大小。超过此长度的值将被截断。否。默认为 1024。
aggregateMultipleValuesaggregateMultipleValues 是一个可选的布尔标志,用于控制聚合 多值维度 的行为。默认值为 true,在处理多值维度时返回字符串化数组。设置为 false 时,函数将返回第一个值。否。默认为 true。

示例

{
"type" : "stringAny",
"name" : "anyString",
"fieldName" : "aString",
"maxStringBytes" : 2048
}

近似聚合

Count distinct (去重计数)

Apache DataSketches Theta Sketch

DataSketches Theta Sketch 扩展提供的聚合器可提供去重计数估计,并支持使用 Apache DataSketches 库中的 Theta Sketch 进行集合并集、交集和差集后聚合。

Apache DataSketches HLL Sketch

DataSketches HLL Sketch 扩展提供的聚合器使用 HyperLogLog 算法提供去重计数估计。

与 Theta Sketch 相比,HLL Sketch 不支持集合运算,更新和合并速度稍慢,但所需的空间显著较小。

Cardinality, hyperUnique
信息

对于新用例,我们建议优先评估 DataSketches Theta SketchDataSketches HLL Sketch。DataSketches 聚合器通常比 Druid 经典的 cardinalityhyperUnique 聚合器具有更高的灵活性和准确性。

Cardinality 和 HyperUnique 聚合器是 Druid 默认提供的旧版实现,同样使用 HyperLogLog 算法提供去重计数估计。上述提到的更新后的 DataSketches Theta 和 HLL 扩展聚合器具有更优的准确性和性能,因此更推荐使用。

DataSketches 团队发布了一份 对比研究,涵盖了 Druid 原始 HLL 算法与 DataSketches HLL 算法。基于 DataSketches 实现的明显优势,我们建议优先使用它们,而非 Druid 原始的 HLL 聚合器。不过,为确保向后兼容性,我们将继续支持经典聚合器。

请注意,hyperUnique 聚合器与 Datasketches HLL 或 Theta Sketch 不兼容。

多列处理

请注意,DataSketches Theta 和 HLL 聚合器目前仅支持单列输入。如果您之前使用 Cardinality 聚合器处理多列输入,下面描述了使用 Theta 或 HLL Sketch 进行等效操作的方法:

  • 多列 byValue Cardinality 可以被单个输入列上的 Theta Sketch 并集所替代。
  • 多列 byRow Cardinality 可以被单个 虚拟列 上的 Theta 或 HLL Sketch 所替代,该虚拟列结合了各个输入列。

直方图和分位数

DataSketches Quantiles Sketch

DataSketches Quantiles Sketch 扩展提供的聚合器使用来自 datasketches 库的数字分位数 DoublesSketch 提供分位数估计和直方图近似。

通常我们推荐该聚合器用于分位数/直方图用例,因为它提供了正式的误差界限,且精度与分布无关。

Moments Sketch (实验性)

Moments Sketch 扩展提供的聚合器是一个实验性聚合器,它使用 Moments Sketch 提供分位数估计。

Moments Sketch 聚合器是作为实验选项提供的。它针对合并速度进行了优化,聚合性能可能高于 DataSketches 分位数聚合器。但 Moments Sketch 的准确性取决于数据分布,因此用户需要通过实验验证该聚合器是否适用于其输入数据。

作为实验的一般指导原则,Moments Sketch 论文 指出,该算法在高熵输入上表现更好。特别是当输入数据由少量聚类的离散值组成时,该算法不太适用。

固定桶直方图 (Fixed Buckets Histogram)

Druid 还提供了一个 简单的直方图实现,它使用固定的范围和固定数量的桶,支持分位数估计,并由桶计数数组支持。

当输入数据的分布允许使用少量桶时,固定桶直方图可以表现良好。

我们不建议一般用途使用固定桶直方图,因为其实用性极大地依赖于数据。不过,它为已经确定固定桶直方图适合其用例的用户提供。

近似直方图 (Approximate Histogram) (已弃用)
信息

Approximate Histogram 聚合器已弃用。目前有许多其他提供更好性能、准确性和内存占用的分位数估计算法。我们建议改用 DataSketches Quantiles

Approximate Histogram 扩展提供的聚合器也提供分位数估计和直方图近似,基于 https://jmlr.org.cn/papers/volume11/ben-haim10a/ben-haim10a.pdf

该弃用聚合器使用的算法高度依赖于分布,并且当输入不符合算法的限制时,其输出会受到严重失真。

DataSketches 团队发布的一项研究 展示了该算法的一些已知失败模式。

  • 该算法的分位数计算可能无法为大范围的秩值提供结果(研究示例中所有低于 0.89 的秩都失效),取而代之返回所有零。
  • 该算法可能完全无法记录分布尾部的峰值。
  • 通常,该算法生成的直方图可能与真实直方图存在显著偏差,且没有误差范围保证。

无法预先确定此聚合器对于给定输入流的行为表现如何,聚合器也不会提供任何迹象表明输出存在严重失真。

基于这些原因,我们弃用了此聚合器,并建议在新的和现有的用例中使用 DataSketches Quantiles 聚合器,不过我们将继续支持 Approximate Histogram 以实现向后兼容性。

表达式聚合

Expression 聚合器

仅在查询时可用的聚合器。使用 Druid 表达式 函数聚合结果,以促进构建自定义函数。

属性描述是否必须
type必须为 "expression"。
name聚合器输出名称。
fields聚合器输入列列表。
accumulatorIdentifierfoldcombine 表达式中标识累加器值的变量。否。默认为 __acc
fold用于从 fields 累加值的表达式。表达式的结果存储在 accumulatorIdentifier 中,并可供下一次计算使用。
combine在合并结果时组合每个段的各种 fold 表达式结果的表达式。输入作为变量(标识为 name)提供给表达式。否。如果表达式在 fields 中只有一个输入,则默认为 fold 表达式。
compare比较器表达式,只能引用两个输入变量 o1o2,其中 o1o2foldcombine 表达式的输出,并且必须遵守 Java 比较器契约。如果未设置,聚合器将尝试回退到适合输出类型的比较器。
finalize最终化表达式,只能引用单个输入变量 o。此表达式用于对 foldcombine 表达式的输出执行任何最终转换。如果未设置,则值不会被转换。
initialValuefold(以及 combine,如果 InitialCombineValue 为 null)表达式的累加器初始值。
initialCombineValuecombine 表达式的累加器初始值。否。默认为 initialValue
isNullUnlessAggregated如果为 true,当聚合器不处理任何行时,将默认输出值设置为 null。如果为 false,Druid 将计算使用初始值运行表达式的结果作为值。否。默认为 true
shouldAggregateNullInputs指示 fold 表达式是否应处理任何 null 输入值。否。默认为 true
shouldCombineAggregateNullInputs指示 combine 表达式是否应处理任何 null 输入值。否。默认为 shouldAggregateNullInputs 的值。
maxSizeBytes可变大小聚合器输出类型(如字符串和数组)在聚合失败前允许增长到的最大字节数。否。默认值为 8192 字节。

示例:“count”聚合器

初始值为 0fold 为处理的每一行添加 1

{
"type": "expression",
"name": "expression_count",
"fields": [],
"initialValue": "0",
"fold": "__acc + 1",
"combine": "__acc + expression_count"
}

示例:“sum”聚合器

初始值为 0fold 为处理的每一行添加 column_a 的数值。

{
"type": "expression",
"name": "expression_sum",
"fields": ["column_a"],
"initialValue": "0",
"fold": "__acc + column_a"
}

示例:“distinct array element”聚合器,按 array_length 排序

初始值为空数组。fold 使用集合语义将 column_a 的元素添加到累加器,combine 合并集合,comparearray_length 对值进行排序。

{
"type": "expression",
"name": "expression_array_agg_distinct",
"fields": ["column_a"],
"initialValue": "[]",
"fold": "array_set_add(__acc, column_a)",
"combine": "array_set_add_all(__acc, expression_array_agg_distinct)",
"compare": "if(array_length(o1) > array_length(o2), 1, if (array_length(o1) == array_length(o2), 0, -1))"
}

示例:使用内置 hyper-unique 的“近似计数”聚合器

类似于 cardinality 聚合器,默认值为空 hyper-unique sketch,foldcolumn_a 的值添加到 sketch 中,combine 合并 sketch,finalize 从累加的 sketch 中获取估计计数。

{
"type": "expression",
"name": "expression_cardinality",
"fields": ["column_a"],
"initialValue": "hyper_unique()",
"fold": "hyper_unique_add(column_a, __acc)",
"combine": "hyper_unique_add(expression_cardinality, __acc)",
"finalize": "hyper_unique_estimate(o)"
}

JavaScript 聚合器

在列集(允许指标和维度)上计算任意 JavaScript 函数。您的 JavaScript 函数预期返回浮点值。

属性描述是否必须
type必须为 "javascript"。
name聚合器输出名称。
fieldNames聚合器输入列列表。
fnAggregateJavaScript 函数,根据当前行值更新部分聚合,并返回更新后的部分聚合。
fnCombine合并部分聚合并返回合并结果的 JavaScript 函数。
fnReset返回“初始”值的 JavaScript 函数。

示例
{
"type": "javascript",
"name": "sum(log(x)*y) + 10",
"fieldNames": ["x", "y"],
"fnAggregate" : "function(current, a, b) { return current + (Math.log(a) * b); }",
"fnCombine" : "function(partialA, partialB) { return partialA + partialB; }",
"fnReset" : "function() { return 10; }"
}
信息

JavaScript 功能默认处于禁用状态。请参阅 Druid JavaScript 编程指南 以获取有关使用 Druid JavaScript 功能的指南,包括如何启用它的说明。

其他聚合

Filtered 聚合器

Filtered 聚合器包装了任何给定的聚合器,但仅聚合给定维度过滤器匹配的值。

这使得同时计算过滤和未过滤聚合的结果成为可能,而无需发出多次查询,并将两个结果用作后聚合的一部分。

如果只需要过滤结果,请考虑在查询本身上放置过滤器。这将快得多,因为它不需要扫描所有数据。

属性描述是否必须
type必须为 "filtered"。
name聚合器输出名称。
aggregator内联聚合器规范。
filter内联 过滤器 规范。

示例

{
"type": "filtered",
"name": "filteredSumLong",
"filter": {
"type" : "selector",
"dimension" : "someColumn",
"value" : "abcdef"
},
"aggregator": {
"type": "longSum",
"name": "sumLong",
"fieldName": "aLong"
}
}

Grouping 聚合器

Grouping 聚合器只能作为包含小计规范(subtotal spec)的 GroupBy 查询的一部分使用。它为每个输出行返回一个数字,允许您推断特定维度是否包含在该行使用的小组(sub-grouping)中。您可以将一个 非空 维度列表传递给此聚合器,该列表 必须 是您正在分组的维度的子集。

属性描述是否必须
type必须为 "grouping"。
name聚合器输出名称。
groupings用于分组集中的列列表。

例如,以下聚合器具有 ["dim1", "dim2"] 作为输入维度

{ "type" : "grouping", "name" : "someGrouping", "groupings" : ["dim1", "dim2"] }

并且在具有 [["dim1", "dim2"], ["dim1"], ["dim2"], []] 作为小计的分组查询中使用,聚合器的可能输出是

查询中使用的小计输出(位表示)
["dim1", "dim2"]0(00)
["dim1"]1(01)
["dim2"]2(10)
[]3(11)

正如示例所示,您可以将输出数字视为无符号的 n 位数字,其中 n 是传递给聚合器的维度数量。如果小组包含位置 X 处的维度,Druid 将数字中位置 X 处的位设置为 0。否则,Druid 将此位设置为 1。