druid查询上手总结

因为业务的需要,接触了关于数据库连接池druid的查询,因为对于这方面的生疏,刚刚开始的时候为了快速上手,仅仅局限于使用。因为很少接触大数据,对于里面的一些概念理解不透彻走了不少的弯路,一周时间的探索,现在终于也有了一个比较正确的认识,所以在这里开篇做一个总结。

0x00 引言

从什么角度去理解druid其实很重要,作为一个前端,一开始我只是把druid当成一个工具来理解,当成是一个以json为查询方式、连接数据库的连接池。结合同事之前编写的代码,导致了我只想知道两个重点:

  1. 特定的查询类型,相应地需要什么样的查询条件组合,首先知道哪些条件是必须的,好组合起来把代码先跑起来;
  2. 使用什么查询类型,会返回什么样的格式的数据?

于是我翻开了文档,把要用的查询方式(timeseries、topN、GroupBy、Time Boundary、Segment Metadata、Datasource Metadata、select、search、scan)都过了一遍,总计9种查询,每种查询都是不同的查询条件并且返回不同格式的数据,毫无疑问非常崩溃……大脑非常抵触这种记忆的方式,于是我前几天不断地往返于文档和代码之间,非常低效。

我开始意识到我现在不能想着赶紧把需求做完,而是应该跳到一个更高的层面去理解druid,于是我带着几个疑问重新开始学习了一遍druid

  1. druid是什么?
  2. druid到底解决了什么问题,带来了什么好处?
  3. druid带来(或实现)了什么概念?

0x01 OLAP

首先从文档中的概览可以知道,druid是一款高性能、面向列的分布式存储,专门为实时数据和历史数据提供亚秒级别的查询而设计。主要用于统计数据的商业智能(OLAP)查询,并且能够支持快速的多维过滤,特设属性分组,以及极快的聚合。

其次需要了解一个关键词OLAP,个人理解druid是对OLAP的具体实现,概念来自于此。

联机分析处理OLAP是一种软件技术,它使分析人员能够迅速、一致、交互地从各个方面观察信息,以达到深入理解数据的目的。它具有FASMI(Fast Analysis of Shared Multidimensional Information),即共享多维信息的快速分析的特征。其中F是快速性(Fast),指系统能在数秒内对用户的多数分析要求做出反应;A是可分析性(Analysis),指用户无需编程就可以定义新的专门计算,将其作为分析的一部 分,并以用户所希望的方式给出报告;M是多维性(Multi—dimensional),指提供对数据分析的多维视图和分析;I是信息性(Information),指能及时获得信息,并且管理大容量信息。 -- 百度百科

其实很好理解,当面对庞大的数据要做分析的时候,观察一些局部琐碎的点实际上没有太大的意义,我们应该要总结一套高效通用的方法去分析,比如分时间点的数据采集,以及对数据的进行聚合,去研究趋势,而OLAP定义了一整套这样便于分析的体系。

对于数据,我们把它当成是个多维度的超立方体,分析者可以通过不同的维度观察数据。

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

对于查询到的数据,定义了以下操作

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

这时候我们再回过头来看druid,已经不再茫然。

0x02 druid

现在我们返回来看druid数据,所有的查询都围绕时间的维度。

timestamp publisher advertiser gender country click price
2011-01-01T01:01:35Z bieberfever.com google.com Male USA 0 0.65
2011-01-01T01:03:63Z bieberfever.com google.com Male USA 0 0.62
2011-01-01T01:04:51Z bieberfever.com google.com Male USA 1 0.45
2011-01-01T01:00:00Z ultratrimfast.com google.com Female UK 0 0.87
2011-01-01T02:00:00Z ultratrimfast.com google.com Female UK 0 0.99
2011-01-01T02:00:00Z ultratrimfast.com google.com Female UK 1 1.53

一段数据中包含了三个组件:

  • timestamp column: 首先它是围绕着时间轴查询的,所以在OLAP中的定义默认第一个维度就是timestamp
  • diamension columns: 维度列(在druid中将timestamp撇开当成一个特殊的个体,剩余的称之为维度),一般为字符串类型,用于过滤数据以及数据聚合分组的依据。(publisher、advertiser、gender、country)
  • metric columns: 度量列,通常是数值,一般用于聚合数据中的计算和聚合后的数值展现。(click, price)
数据分片

druid可以以(数据源-时间范围-版本号-段号)结合为一个维度配合时间戳对数据进行切片,这样的一个单元称之为段(segment)

比如我们为了观察一篇文章点击量上升的趋势,我们每隔一个小时灌入一次数据,因此产生了两个分段

  • 段sampleData_2011-01-01T01:00:00:00Z_2011-01-01T02:00:00:00Z_v1_0
timestamp publisher advertiser gender country click
2011-01-01T01:00:00Z ultratrimfast.com google.com Male USA 1800
2011-01-01T01:00:00Z bieberfever.com google.com Male USA 2912
  • 段sampleData_2011-01-01T02:00:00:00Z_2011-01-01T03:00:00:00Z_v1_0
timestamp publisher advertiser gender country click
2011-01-01T02:00:00Z ultratrimfast.com google.com Male USA 2200
2011-01-01T02:00:00Z bieberfever.com google.com Male USA 3309
上卷(rollup)

现在我们要看每个时间段内产生的点击量的总和。我们假设每个分段内,只采集了一次数据,时间点相同,基于timestamp 做一次rollup,于是产生了两条数据,点击数产生了一次聚合。

timestamp click
2011-01-01T01:00:00Z 4712
2011-01-01T02:00:00Z 5509

0x03 查询(query)

我们已经将用到的基本概念都过了一遍,现在是时候落地到查询了。druid的原生查询语言是JSON,当然各大开源社区的贡献使其也支持了其他语言的查询,包括SQL。

druid的查询分为三大类,分别是聚合查询,元数据查询以及普通查询

普通的查询包括

聚合查询

元数据查询

我们也不通篇过文档了,普通的查询没什么好讲的,只有一个需要注意的点,那就是select在查询大量的数据的时候,很消耗内存,如果没有分页的需求,可以用scan替代。

元数据的查询,主要不是基于业务的查询,而是对当前表的属性,或者是定义列的类型这一类属性的查询,比如xxx表中"country"是什么类型的数据,xxx表收集数据起止时间,或者当前分段的版本是什么之类的信息。

主要需要理解的是三种内置的聚合查询,本质上做的操作是这样的

  • timeseries: 时序查询,实际上即是对数据基于时间点(timestamp)的一次上卷。适合用来看某几个度量在一个时间段内的趋势。排序可按时间降序或升序。
  • topN: 在时间点的基础上,又增加了一个维度(OLAP的概念算两个维度),进而对源数据进行切片,切片之后分别上卷,最后返回一个聚合集,你可以指定某个指标作为排序的依据。官方文档称这对比单个druid dimension 的groupBy 更高效。适合看某个维度下的时间趋势,(比如美国和中国十年内GDP的增长趋势比对,在这里除了时间外国家就是另外一个维度)
  • GroupBy: 适用于两个维度以上的查询,druid会根据维度切块,并且分别上卷,最后返回聚合集。相对于topN而言,这是一个向下钻取的操作,每多一个维度意味着保留更多的细节。(比如增加一个行业的维度,就可以知道美国和中国十年内,每一年不同行业贡献GDP的占比)

查询的条件

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

0x04 总结

学习druid的过程,最大的收获其实并不是掌握druid本身,而是学到了他贯彻的OLAP的一些概念,从一开始的毫无所知,带着一点线索向上探索,到慢慢知晓通篇,真是一个有趣的过程,实际上懂了OLAP,很快也能掌握其他数据库的查询,真正做到了触类旁通,带着这套思路相信很快也能上手SQL了,开心。希望能对大家上手起到帮助吧,共勉!

你可能感兴趣的:(druid,聚合,查询,数据库连接池)