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