点击上方蓝色字体,选择“设为星标”

回复”资源“获取更多惊喜

大数据技术与架构

点击右侧关注,大数据开发领域最强公众号!

大数据真好玩

点击右侧关注,大数据真好玩!

Apache Druid是一款优秀的OLAP引擎,众所周知数据存储格式对一款存储系统来说是最核心的组件,Druid的数据格式是自定义的,以此保证了在海量数据下的亚秒级查询。本文深入分析Druid V1版本数据存储格式,包括索引结构和数据在磁盘中的存储方式。在阅读本文之前希望您对Druid和数据存储有简单了解。

Druid的存储方式是列式的,每个列为一个逻辑文件,列与列之间的数据格式是相对独立的。与传统OLAP系统一样,Druid的列分为维度与度量两种,其中维度列因为需要被检检索,所以设计了索引,维度列的数据格式也是Druid数据结构的核心;相对的度量列只需要存储行值就可以。为了方便阐述数据格式,本文以一个广告效果分析作为例子进行分析,图1中是样例数据,请一定注意它是聚合后的数据,而不是原始数据。

维度数据结构

上文提到维度是Druid存储结构的核心,并且各个维度是相对独立存储的,所以我们可以通过分析单个维度的数据结构,来窥探Druid的存储结构。图2展示了“city”维度和两个度量的逻辑存储结构,整体上Druid维度的索引包含三部分:字典、编码后的维度值、倒排索引,接下来详细分析这三部分。

字典

字典是将列的所有值去重,然后按照字典顺序排序的值组成的数组,虽然字典中只存储了排序后的维度值,但是它还隐含了另一个信息,那就是每个维度值的编码值,编码值就等于数组的下标。字典的设计目的有两个:一是维度值可以使用编码后的整数表示,而不是实际的值,编码值一般可以节约存储空间;二是编码后的整数是定长的,磁盘中定长存储可以省去定位单个值的offset length等索引信息的开销,最终还是能节省存储空间。

图3展示了Druid字典的逻辑结构和物理结构,Druid字典采用了线性的数组结构。因为字典中的值是不定长的,所以物理结构中有一段index部分,其中记录了每个值的offset;data部分每个值的头部记录了该值的长度。这样的设计才能定位到任意一个行的值。

编码后的维度值

Druid是一个预聚合的方案,但是其聚合不是按照一个维度的group-by聚合,而是按照所有维度的group-by聚合,对于图1中的数据已经是按照聚合过了。可以看出对于单一维度而言,编码过后的维度值依然可能重复,所以每个维度的行信息不能用字典代替,而需要额外存储。

编码后的维度值都是一个个的整数。为了保证单一值在磁盘中能快速定位,在整个维度范围内这些整数需要是定长的,因为定长元素组成的数组可以通过计算直接定位到某一个元素。同时为了节约存储空间这些整数不一定需要用4个字节表示,它的长度取决于该维度在单一数据文件内的唯一值的数量,Druid采用了采用了变长整数编码的方式,具体如下:

1 – 2^8-1 => 1 byte
2^8 - 2^16-1 => 2 bytes
2^16 - 2^24-1 => 3 bytes
2^24 - 2^32-1 => 4 bytes
2^32 - 2^40-1 => 5 bytes
...

以图1中“city”维度为例,它包含唯一值3个,所以每个值用1个字节表示。

图4展示了编码后维度值的逻辑结构和物理结构,在逻辑上整个维度是一个线性的结构,但是在物理存储上数据结构中包含了offset索引和元素length部分,这很明显是存储非定长数据的。原来Druid将整个线性结构首先划分成了一个个分组,每个分组大小不超过64KB,而分组又进行了压缩,压缩后的分组已经是非定长的了,所以站在整个数据结构的角度,需要按照非定长数据的格式进行存储。

将整个整数数组进行分组压缩的设计思路,其背后的考量点主要是:一是对于磁盘存储压缩是有必要的,因为能减小空间占用和传输消耗;二是分组也是有必要的,因为绝大多数读取数据的场景不会涉及到所有的分组,而是部分分组,分组后一次查询只涉及到了少数分组,对于查询速度的提升有极大帮助。

倒排索引

最后是倒排索引部分,对于字典中的每个元素,Druid都会生成一个Bitmap,其中1表示该bit下标对应的行的值是对应字典元素的值,反之不是。

Bitmap数据是基于聚合后的数据的,所以它的长度和原始数据的行数是没有关系的。从图5中“Beijing”对应的Bitmap可以看出,它基于图1中的聚合后的数据,而不是原始数据,所以Bitmap的长度是4。

Druid的反向索引采用的是Bitmap的方案,因为字典中每个元素对应的Bitmap的长度都是一样的,所以物理存储上可以采用定长的方式?其实不是的,出于节省存储空间的考虑,Druid将每个Bitmap进行了压缩,一般Bitmap数据结构的压缩比例是比较大的,所以压缩的是有必要的。因为压缩后数据长度不相同了,所以存储上需要按照非定长数据进行存储。

数组

Druid是支持数组数据类型维度的,对于数组数据类型Druid如何存储呢?整体上数组的存储方式还是字典、编码后的维度值、倒排索引三个部分。其中字典和倒排索引部分是跟单值类型的维度的存储方式没有任何区别。

但是在编码后的维度值部分是有区别的,对于单值维度这部分的逻辑结构是一个线性列表(这里暂时不考虑分组),但是对于数组类型的维度,它其实是一个二层的层次结构,外层是一个非定长的线性列表,线性列表的每个元素也就是内层,是一个定长的线性列表。对于整个数据结构来说,在物理结构上依然可以进行分组和压缩。

存储结构小结

对于物理结构来说其元素是否定长,对其存储方式起到决定作用,图6总结了定长和非定长的存储模式,请注意这里没有考虑分组和压缩。

Druid对线性非定长存储结构有这大量的应用,它遵循图6的总结,只是在元数据部分稍有不同,现总结如下:

version:占用 1byte
allowReverseLookup:1byte ,是否允许反向查找,指根据Value反查index, 用于Dictionary字典查找
numBytesUsed :4bytes ,所占字节数
numElements:4bytes,元素的总数量

如何使用

最后简单分析下Druid在查询中如何使用到以上数据结构,为了聚焦问题,假设查询只命中了一个数据文件,这样可以忽略多个数据文件的结果合并等问题。我们以下面简单查询为例:

select city, sum(click_cnt) from table_t where category=0 or category=1 group by city

图8展示了查询流程,其中第1.6步用到了字典结构,第3步用到了倒排索引数据结构,第4部用到了编码后的维度值数据结构。

数据湖VS数据仓库?湖仓一体了解一下

Kylin、Druid、ClickHouse核心技术对比

万字长文,超全Spark性能优化总结

代达罗斯之殇-大数据领域小文件问题解决攻略

大数据可视化从未如此简单 - Apache Zepplien全面介绍

Kylin 大数据下的OLAP解决方案和行业典型应用

版权声明:

本文为大数据技术与架构整理,原作者独家授权。未经原作者允许转载追究侵权责任。

微信公众号|import_bigdata

编辑| 《大数据技术与架构》

文章链接| http://www.jackywoo.cn/data-structure-in-druid/

欢迎点赞+收藏+转发朋友圈素质三连

文章不错?点个【在看】吧! ????

大话 Druid 存储结构相关推荐

  1. SQL SERVER大话存储结构(2)

    阅读目录(Content) 1 行记录如何存储 1.1 堆表 1.2 聚集索引表格 2 非聚集索引结构 3 非聚集索引键值内容 3.1 堆表上的非聚集索引 3.2 聚集索引表(唯一)的非聚集索引 3. ...

  2. 大话数据结构 -07-1 图的定义、抽象数据类型与存储结构

    1. 定义 在图结构中,结点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关. 2. 与线性表.树结构的区别 3. 相关定义 (1)无向.有向 与图边或者弧相关的数字叫做权(Weight), ...

  3. 《大话数据结构》----第三章---线性表链式存储结构

    目录 一.为啥要单独说线性表的链式存储结构? 二.这些链式存储结构分别是什么样的? 2.1 单链结构是怎么样的? 2.2 静态链表又是怎么定义的呢? 2.3循环链表是如何定义的? 2.4双向链表是为什 ...

  4. 《大话数据结构》5一文学会数据结构中的静态链表存储结构(概念,实例,代码)

    静态链表 1.静态链表基本介绍 (1)静态链表:用数组来代替指针,来描述单链表.我们把用数组描述下标的链表叫做静态链表.也叫游标实现法. (2)首先让数组的元素是两个数据域组成,data 和cur.也 ...

  5. 链表list(链式存储结构实现)_5 线性表的链式存储结构

    系列文章参考资料为<大话数据结构>,源码为个人私有,未经允许不得转载 线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,可以使连续的,也可以不连续,也就意味这些元素可以 ...

  6. 链表list(链式存储结构实现)_数据结构知否知否系列之 — 线性表的顺序与链式存储篇(8000 多字长文)...

    从不浪费时间的人,没有工夫抱怨时间不够. -- 杰弗逊 线性表是由 n 个数据元素组成的有限序列,也是最基本.最简单.最常用的一种数据结构. 作者简介:五月君,Nodejs Developer,热爱技 ...

  7. 线性表之链式存储结构_单链表相关算法

    在存储结构上,不需要连续的存储空间,需要上一个结点的指针域 指向下一个结点即可,找到一个结点就可以找到下一个结点. 学习教材是大话数据结构,加上自己的一些个人理解.这个算法 有点绕,需要对指针 相关内 ...

  8. 图的常见存储结构及各自的优缺点

    以下说法均建立在简单图上,即无环无重复边的图. 本文将介绍图的常见存储结构及各自的优缺点 邻接矩阵 邻接表 十字链表 邻接多重表 边集数组 邻接矩阵 用两个数组来表示图:一个一维数组存储图中顶点信息, ...

  9. 线性表-链式存储结构

    3.6 线性表的链式存储结构 3.6.1 顺序存储结构不足的解决办法 前面我们讲的线性表的顺序存储结构.它是有缺点的,最大的缺点就是插入和删除时需要移动大量元素,这显然就需要耗费时间.能不能想办法解决 ...

最新文章

  1. 波士顿动力CEO:不排斥军方订单,就想你粗暴地对待机器狗
  2. Smartforms 设置纸张打印格式
  3. HaProxy+Keepalived+Mycat高可用群集配置
  4. [CodeForces]Codeforces Round #432 (Div. 2)
  5. vscode主题_VScode霓虹发光主题SynthWave 84|透明主题
  6. 如何使用DOSBox软件编写运行汇编语言程序
  7. 如何写出一份好的解决方案
  8. JavaScript归纳总结
  9. Spark总结之RDD(四)
  10. Writeback和Writethrough区别
  11. 计算机二级Python真题(七)
  12. 转载之-中值滤波均值滤波
  13. 使用python获取微医数据
  14. Hexo+NexT 增加精品文章方法
  15. 为何使用云原生应用架构 二 :独霸天下之四大绝技
  16. 有赞VS光云科技,电商SaaS的未来殊途同归
  17. 在iPhone上实现标签云
  18. Capture ORCAD CIS导出原理库OLB文件
  19. Kenney Assets - 提供数以万计免费商用的游戏制作素材下载,包括 2d、3d素材,游戏音效和游戏 UI
  20. springboot整合支付宝微信支付案例+代码

热门文章

  1. 新媒体运营——客户沟通方式
  2. 凸显以专业课程体系为核心进行职业院校实训基地建设
  3. 标准c语言局域网文件传输,winsocket局域网文件传输系统源代码(C语言)+winsocket
  4. 南京邮电大学计算机考研专硕初试经验分享
  5. 金融+科技,民生银行与华为携手打造数字化智能银行
  6. golang浅拷贝与深拷贝
  7. iOS11下UITableView侧滑删除详解
  8. 解决spring定时任务执行两次和tomcat部署缓慢的问题
  9. RecyclerView 点击位置错乱问题
  10. Quartus安装及使用教程(13版附安装包)