抖音技术能力大揭密!钜惠大礼、深度体验,尽在火山引擎增长沙龙,就等你来! 立即报名>> 了解详情
写点什么

Apache Kylin 权威指南(八):Rowkey 优化

2020 年 4 月 20 日

Apache Kylin权威指南(八):Rowkey 优化

编者按:本文节选自华章科技大数据技术丛书 《Apache Kylin 权威指南(第 2 版)》一书中的部分章节。


Rowkey 优化

前面章节的侧重点是减少 Cube 中 Cuboid 的数量,以优化 Cube 的存储空间和构建性能,统称以减少 Cuboid 的数量为目的的优化为 Cuboid 剪枝。在本节中,将重点通过对 Cube 的 Rowkey 的设置来优化 Cube 的查询性能。


Cube 的每个 Cuboid 中都包含大量的行,每个行又分为 Rowkey 和 Measure 两个部分。每行 Cuboid 数据中的 Rowkey 都包含当前 Cuboid 中所有维度的值的组合。Rowkey 中的各个维度按照 Cube Designer→Advanced Setting→RowKeys 中设置的顺序和编码进行组织,如图 1 所示。



图 1 Rowkey 的设置页面


在 Rowkeys 设置页面中,每个维度都有几项关键的配置,下面将一一道来。


调整 Rowkey 顺序

在 Cube Designer→Advanced Setting→Rowkeys 部分,可以上下拖动每一个维度来调节维度在 Rowkey 中的顺序。这种顺序对于查询非常重要,因为目前在实现中,Kylin 会把所有的维度按照显示的顺序黏合成一个完整的 Rowkey,并且按照这个 Rowkey 升序排列 Cuboid 中所有的行,参照前一章的图 16。


不难发现,对排序靠前的维度进行过滤的效果会非常好,比如在图 16 中的 Cuboid 中,如果对 D1 进行过滤,它是严格按照顺序进行排列的;如果对 D3 进行过滤,它仅是在 D1 相同时在组内顺序排列的。


如果在一个比较靠后的维度进行过滤,那么这个过滤的执行就会非常复杂。以目前的 HBase 存储引擎为例,Cube 的 Rowkey 就对应 HBase 中的 Rowkey,是一段字节数组。我们目前没有创建单独的每个维度上的倒排索引,因此对于在比较靠后的维度上的过滤条件,只能依靠 HBase 的 Fuzzy Key Filter 来执行。尽管 HBase 做了大量相应的优化,但是在对靠后的字节运用 Fuzzy Key Filter 时,一旦前面维度的基数很大,Fuzzy Key Filter 的寻找代价就会很高,执行效率就会降低。所以,在调整 Rowkey 的顺序时需要遵循以下几个原则:


  • 有可能在查询中被用作过滤条件的维度,应当放在其他维度的前面。

  • a) 对于多个可能用作过滤条件的维度,基数高的(意味着用它进行过滤时,较多的行被过滤,返回的结果集较小)更适合放在前面;

  • b) 总体而言,可以用下面这个公式给维度打分,得分越高的维度越应该放在前排:

  • 排序评分=维度出现在过滤条件中的概率*用该维度进行过滤时可以过滤掉的记录数。

  • 将经常出现在查询中的维度,放在不经常出现的维度的前面,这样,在需要进行后聚合的场景中查询效率会更高。

  • 对于不会出现在过滤条件中的维度,按照其基数的高低,优先将低基数的维度放在 Rowkey 的后面。这是因为在逐层构建 Cuboid、确定 Cuboid 的生成树时,Kylin 会优先选择 Rowkey 后面的维度所在的父 Cuboid 来生成子 Cuboid,那么基数越低的维度,包含它的父 Cuboid 的行数就越少,聚合生成子 Cuboid 的代价就越小。


选择合适的维度编码

2.4.3 节介绍过,Apache Kylin 支持多种维度编码方式,用户可以针对数据特征,选择合适的编码方式,从而减小数据的存储空间。在具体使用过程中,如果用错了编码方式,可能会导致构建和查询的一系列问题。这里要注意的事项包括:


  • 字典(Dictionary)编码(默认的编码)不适用于高基数维度(基数值在 300 万以上)。主要原因是,字典需要在单节点内存中构建,并在查询的时候加载到 Kylin 内存;过大的字典不但会使得构建变慢,还会在查询时占用很多内存,导致查询缓慢或失败,因此应该避免对高基数维度使用字典编码。如果实际中遇到高基数维度,首先思考此维度是否要引入 Cube 中,是否应该先对其进行泛化(Generalization),使其变成一个低基数维度;其次,如果一定要使用,那么可以使用 Fixed_length 编码,或 Integer(如果这列的值是整型)编码。

  • Fixed_length 编码是最简单的编码,它通过补上空字符(如果维度值长度小于指定长度))或截断(如果维度值长度大于指定长度),从而将所有值都变成等长,然后拼接到 Rowkey 中。它比较适合于像身份证号、手机号这样的等长值维度。如果某个维度长度变化区间比较大,那么你需要选择一个合适的长度:长度过短会导致数据截断从而失去准确性,长度过长则导致空间浪费。


按维度分片

在 3.3 节中介绍过,系统会对 Cuboid 中的数据在存储时进行分片处理。默认情况下,Cuboid 的分片策略是对于所有列进行哈希计算后随机分配的。也就是说,我们无法控制 Cuboid 的哪些行会被分到同一个分片中。这种默认的方法固然能够提高读取的并发程度,但是它仍然有优化的空间。按维度分片提供了一种更加高效的分片策略,那就是按照某个特定维度进行分片(Shard By Dimension)。简单地说,当你选取了一个维度用于分片后,如果 Cuboid 中的某两行在该维度上的值相同,那么无论这个 Cuboid 最终被划分成多少个分片,这两行数据必然会被分配到同一个分片中。


这种分片策略对查询有着极大的好处。我们知道,Cuboid 的每个分片会被分配到存储引擎的不同物理机器上。Kylin 在读取 Cuboid 数据的时候会向存储引擎的若干机器发送读取的 RPC 请求。在 RPC 请求接收端,存储引擎会读取本机的分片数据,并在进行一定的预处理后发送 RPC 回应(如图 2 所示)。以 HBase 存储引擎为例,不同的 Region 代表不同的 Cuboid 分片,在读取 Cuboid 数据的时候,HBase 会为每个 Region 开启一个 Coprocessor 实例来处理查询引擎的请求。查询引擎将查询条件和分组条件作为请求参数的一部分发送到 Coprocessor 中,Coprocessor 就能够在返回结果之前对当前分片的数据做一定的预聚合(这里的预聚合不是 Cube 构建的预聚合,是针对特定查询的深度的预聚合)。



图 2 存储引擎执行 RPC 查询


如果按照维度划分分片,假设是按照一个基数比较高的维度 seller_id 进行分片的,那么在这种情况下,每个分片承担一部分 seller_id,各个分片不会有相同的 seller_id。所有按照 seller_id 分组(group by seller_id)的查询都会变得更加高效,因为每个分片预聚合的结果会更加专注于某些 seller_id,使得分片返回结果的数量大大减少,查询引擎端也无须对各个分片的结果做分片间的聚合。按维度分片也能让过滤条件的执行更加高效,因为由于按维度分片,每个分片的数据都更加“整洁”,便于查找和索引。


图书简介https://item.jd.com/12566389.html



相关阅读


Apache Kylin权威指南(一):背景历史和使命


Apache Kylin权威指南(二):工作原理


Apache Kylin权威指南(三):技术架构


Apache Kylin权威指南(四):核心概念


Apache Kylin权威指南(五):Getting Started


Apache Kylin权威指南(六):Cuboid剪枝优化


Apache Kylin权威指南(七):剪枝优化工具


2020 年 4 月 20 日 10:00854

评论

发布
暂无评论
发现更多内容

2个月从0到1,一年5次迭代,百度“量桨”效率喷涌背后的工作秘诀

脑极体

读《小岛经济学有感》

箭上有毒

读书笔记 4月日更

mmkv跨进程,面试字节跳动Android研发岗,灵魂拷问

欢喜学安卓

android 程序员 面试 移动开发

150页的剑指Offer解答PDF,它来了!!!

秦怀杂货店

翻译:《实用的Python编程》InstructorNotes

codists

Python

小米java社招面试记录,带备战思路

Java架构师迁哥

图算法系列之深度优先搜索(一)

Silently9527

Java 深度优先搜索 图算法

ndk开发环境,个人开发者做一款App需要知道的事情,绝对干货

欢喜学安卓

android 程序员 面试 移动开发

Vue源码思想在工作中的应用

执鸢者

Vue 前端

聪明人的训练(二十四)

Changing Lin

4月日更

当我看技术文章的时候,我在想什么?

why技术

Java

一场关于演讲的演讲

Jxin

容器 & 服务: 扩容

程序员架构进阶

容器 k8s 28天写作 弹性扩容 4月日更

PassJava 初始化项目和添加微服务

悟空聊架构

边缘计算加持下的智慧社区

浪潮云

边缘计算

比微信文件传输助手更好用的传输工具|Telegram

彭宏豪95

微信 效率 文件传输 4月日更 Telegram

解决方案的设计与积累——课程总结

Deborah

安卓rxjava面试,面试一路绿灯Offer拿到手软,吊打面试官系列!

欢喜学安卓

android 程序员 面试 移动开发

安卓rxjava使用,4面字节跳动拿到Offer,面试必问

欢喜学安卓

android 程序员 面试 移动开发

Java虚拟机原理

风翱

JVM 4月日更

【Node专题】Node 与 Go 的认识

南吕

Node 后端开发 4月日更

【go专题】Context的理解

南吕

Golag 4月日更

当时尚撞上区块链,为潮酷创意赋予专属

CECBC区块链专委会

时尚产业

BUG!从编写 Loader 到窥探大佬 Debug 全过程

HZFEStudio

小程序 webpack 构建工具

如何减少管理层级?

石云升

团队建设 28天写作 职场经验 管理经验 4月日更

你的故事,触动了我的心

小天同学

读后感 读书总结 4月日更 皮囊

2021|南吕

南吕

生活随想 4月日更

MBP恢复记(体验rm -rf /*)

SamGo

学习经验

网络协议学习笔记Day3

穿过生命散发芬芳

网络协议 4月日更

NumPy之:标量scalars

程序那些事

Python 数据分析 Numpy 程序那些事 scalar

新思科技发布《疫情中的安全隐患:移动应用程序安全现状》报告

InfoQ_434670063458

App 新思科技 移动应用程序安全

Study Go: From Zero to Hero

Study Go: From Zero to Hero

Apache Kylin权威指南(八):Rowkey 优化-InfoQ