Apache Druid 学习:组件以及查询类型

Apache Druid 学习:组件以及查询类型

OLAP

基本概念

维度(Dimension): 指的是观察数据的一个角度,是考虑问题的一类属性,这些属性的集合统称为一个维。
维的级别(Level): 对数据的观察还存在细节程度的不同,在druid中一般表示为时间的粒度(granularity),比如一秒,一分钟,一小时,一天……
度量(Measure): 度量是用来聚合分析计算的数字信息,在druid中称为”metrics”,它可以是存储在数据库中,也可以是通过策略计算得出的。比如一篇文章的点击数、或者是根据评论数、点击数、转发数计算出的热点值

对于数据处理

向下钻取(Drill-down)/上卷(Roll-up): 改变维的层次和级别,变换分析的粒度。Roll-up在于提升维的级别(或者称粒度)或者减少维度来聚合数据,展现总览,Drill-down反之,降低维的级别(或者称粒度)或增加维度来查看细节
切片(slice)和切块(dice): 当维度为两个时,我们对获取数据(查询)的操作称之为切片,当维度的数量大于两个时,我们称之为切块
旋转(Pivoting): 变换维的方向,例如表格中的行列互换

查询条件参数

字段名 描述 是否必须
queryType 查询类型,对应聚合查询下的类型值:timeseries、topN、groupBy等 是
dataSource 数据源,类似关系数据库中表的概念,对应数据导入时Json配置属性dataSource值 是
descending 返回结果是否逆序,默认值为否(正序) 否
intervals 查询时间区间 是
filter 对Dimension进行过滤,可以根据情况对几个维度组合不同的filter类型(and、or、not、bound),还可以根据需要定义javascript function进行过滤 否
aggregations 指定度量在聚合时候的计算策略,例如相加、或者求平均值、又或者取最后一个值,在内置类型不满足的情况下可以使用javascript。比如某手游中我统计了我每一局击杀小怪数量,以及野怪的数量,通过聚合策略sum,我能知道我从开号以来击杀了多少小怪和野怪。 否
postAggregations 后聚合策略,提供了多个度量组合生成新度量的能力,主要有利于聚合计算的抽象,避免对一些指标的重复计算。举个例子,假如我需要一个度量,是我击杀小怪和野怪的总和,那么,我只需要在后聚合阶段计算,只需要拿小怪和野怪的数量相加一次,大大地提高了计算效率。 否
granularity 查询的时间粒度,最细粒度为秒,最大粒度为all,提供了时间维度级别的调整并对数据进行上卷和向下钻取的能力 是
dimensionSpec 提供了维度在聚合前输出展示值定制的能力,比如在Dimension age一列中,拿到的是字符串类型的数字,我希望转成数字类型,又或者定制一个javascript function,统一以 ${age} year old的形式展现 否
limit 返回结果数量限制 否
context 表示对当前查询本身的一些配置,比如设置查询超时的时间,又比如是否使用缓存,在通用的配置基础上,每种查询类型还有特定的配置,详见文档 否

基本组件

filter

过滤器,在查询语句中是一个json对象,用来对维度进行筛选,表示满足filter的是我们需要的数据。类似于SQL中的where。

类型 功能
SelectorFilter 功能类似于SQL中的where key=value
AndFilter, OrFilter, NotFilter 功能类似于SQL中and、or、not三种过滤器。支持递归嵌套,可以构造出丰富的逻辑表达式
RegexFilter 正则表达式,支持任意维度值的java正则
SearchFilter 通过字符串匹配维度,支持多种表达式
InFilter 功能类似于SQL中where key in (value1, value2)
IntervalFilter 针对于时间维度过滤
BoundFilter 功能类似于SQL中的大于、小于、等于三种算子
JavaScriptFilter 上述filter均不能满足可以自己写JavaScript来过滤维度

aggregator

聚合可以在采集数据时规格部分的一种方式,汇总数据进入Druid之前提供。
聚合也可以被指定为在查询时多查询的部分,聚合类型如下:

类型 功能
CountAggregator SQL count(key)
SumAggregator SQL sum(key)
MaxAggregator, MinAggregator SQL max(key), min(key)
DistinctCountAggregator SQL count(distinct key)
JavaScriptAggregator 上述aggregator均不能满足可以自己写JavaScript来定义计算

post-aggregator

类型 功能
ArithmeticPostAggregator 支持对聚合后指标进行”+ - * / quotient”计算
FieldAccessPostAggregator 直接获取聚合的字段(维度,指标)
ConstantPostAggregator 返回常数
JavaScriptPostAggregator 上述postAggregator均不能满足可以自己写JavaScript来定义计算

查询类型

聚合查询

timeseries

时序查询,实际上即是对数据基于时间点(timestamp)的一次上卷。适合用来看某几个度量在一个时间段内的趋势。排序可按时间降序或升序

字段名 描述 是否必须
queryType 查询类型,必须为 “timeseries” 是
dataSource 数据源,比如 “wikipedia” 是
descending 返回结果是否逆序,默认值为否(正序) 否
intervals 查询时间区间 是
granularity 聚合粒度,粒度决定如何在跨时间维度得到数据块 是
filter 否
aggregations 否
postAggregations 否
limit 否
context 否

context:

1.grandTotal

2.零填充
如果时间范围内没有值,则会填充0
时间序列查询通常用零填充空的内部时间段。例如,如果您对间隔2012-01-01 / 2012-01-04发出“天”粒度时间序列查询,而2012-01-02没有数据存在,您将收到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[
{
"timestamp": "2012-01-01T00:00:00.000Z",
"result": { "sample_name1": <some_value> }
},
{
"timestamp": "2012-01-02T00:00:00.000Z",
"result": { "sample_name1": 0 }
},
{
"timestamp": "2012-01-03T00:00:00.000Z",
"result": { "sample_name1": <some_value> }
}
]

topN

在时间点的基础上,又增加了一个维度(OLAP的概念算两个维度),进而对源数据进行切片,切片之后分别上卷,最后返回一个聚合集,你可以指定某个指标作为排序的依据。官方文档称这对比单个druid dimension 的groupBy 更高效。适合看某个维度下的时间趋势,(比如美国和中国十年内GDP的增长趋势比对,在这里除了时间外国家就是另外一个维度)

字段名 描述 是否必须
queryType 查询类型,必须为 “topN” 是
dataSource 数据源,比如 “wikipedia” 是
intervals 查询时间区间 是
granularity 聚合粒度,粒度决定如何在跨时间维度得到数据块 是
filter 否
aggregations 否
postAggregations 否
dimension 除了时间之外聚合的维度,只能定义一个维度 是
threshold topN中的N,例如:希望查询到top2,则值为2 是
metric topN中用来排序的指标 是
context 否

groupBy

适用于两个维度以上的查询,druid会根据维度切块,并且分别上卷,最后返回聚合集。相对于topN而言,这是一个向下钻取的操作,每多一个维度意味着保留更多的细节。(比如增加一个行业的维度,就可以知道美国和中国十年内,每一年不同行业贡献GDP的占比)
注意:如果要使用时间作为唯一分组进行聚合,或者在单个维度上使用有序groupBy进行聚合,请优先考虑使用Timeseries和TopN查询。在某些情况下,它们的性能可能会更好。有关更多详细信息,请参见下面的替代方法。

字段名 描述 是否必须
queryType 查询类型,必须为 “groupBy” 是
dataSource 数据源,比如 “wikipedia” 是
dimensions 需要聚合的所有维度 是
limitSpec 同关系型数据库中的limit 否
having 同关系型数据库中的having 否
granularity 聚合粒度,粒度决定如何在跨时间维度得到数据块 是
filter 否
aggregations 否
postAggregations 否
intervals 查询时间区间 是
subtotalsSpec 类似于的grouping sets 否
context 否

普通查询

select

类似SQL中的select操作,select用来查看Druid中存储的数据,并支持按照指定过滤器和时间查看指定维度和指标。不支持aggregations和post aggregations

注意:建议您尽可能使用scan查询类型而不是select。在涉及大量segment的情况下,select查询可能具有很高的内存和性能开销,但是scan查询没有此问题。
两者之间的主要区别是“扫描”查询不支持分页。但是,即使没有分页,scan查询类型也能够返回几乎无限数量的结果,使得分页在许多情况下是不必要的。

字段名 描述 是否必须
queryType 查询类型,必须为 “select” 是
dataSource 数据源,比如 “wikipedia” 是
intervals 查询时间区间 是
descending 返回结果是否逆序,默认值为否(正序) 否
filter 否
dimensions 需要查询的维度列表 否
metrics 需要查询的指标列表 否
granularity 聚合粒度,粒度决定如何在跨时间维度得到数据块,默认是Granularity.ALL 否
pagingSpec 分页 是
context 否

scan

扫描查询以流模式返回行,Select查询和Scan查询之间的最大区别是,Scan查询子返回给客户端数据之前不会将所有行数据保留在内存中
而select查询将把行保留在内存中,如果返回太多行,则会导致内存压力。扫描查询可以返回所有行,而无需发出另一个分页查询。

除了将scan查询发送给server的用法外,还可以直接向historical历史记录进程或streaming ingestion流式提取任务发出扫描查询。如果要并行检索大量数据,这将很有用。

字段名 描述 是否必须
queryType 查询类型,必须为 “scan” 是
dataSource 数据源,比如 “wikipedia” 是
intervals 查询时间区间 是
resultFormat 返回结果类型:list,compactedList或valueVector。目前仅list和compactedList受支持。默认是list 否
filter 否
columns 需要scan的维度和指标,默认为所有 否
batchSize 返回数据之前默认缓存最多多少行 否
limit 查询返回最大的数据条目,如果不指定,则返回所有的数据 否
order 返回数据的order,基于timestamp,并且只有__time被包含在columns中才生效 否
legacy 否
context 否

类似SQL中的Like操作,但是支持更多的匹配操作

字段名 描述 是否必须
queryType 查询类型,必须为 “search” 是
dataSource 数据源,比如 “wikipedia” 是
granularity 聚合粒度,粒度决定如何在跨时间维度得到数据块 是
filter 否
limit 每个历史进程的最大查询返回数据条目(默认是1000) 否
intervals 查询时间区间 是
searchDimensions 需要search的维度(默认是所有维度),key like value中的key 否
query search维度需要匹配的value,key like value中的value 是
sort 指定应如何对搜索结果进行排序,包括字典编排(默认排序),字母数字,strlen和数字排序 否
context 否

元数据查询

time bounding

segment metadata

dataSource metadata