前言

下面通过对kylin构建cube流程的分析来介绍cube优化思路。

创建hive中间表

kylin会在cube构建的第一步先构建一张hive的中间表,该表关联了所有的事实表和维度表,也就是一张宽表。

优化点:

1. hive表分区优化,在构建宽表的时候,kylin需要遍历hive表,事实表和维度表如果是分区表,那么会减少遍历时间

2. hive相关配置调整,join相关配置,mapreduce相关配置等

创建完成后,为了防止文件大小不一致的情况,kylin又基于hive做了一次重均衡操作,

`kylin.engine.mr.mapper-input-rows=1000000`,默认每个文件包含100w的数据量

代码 `CreateFlatHiveTableStep`

找出所有维度的基数

通过HyperLogLog 算法找出去重后的维度列,如果某个维度的基数很大,那么这种维度为被称为ultra high cardinality column(UHC),也就是超高基数维度。那么如何处理这类维度呢?

业务层处理UHC

比如时间戳维度基数可能是亿级的,可以转成为日期,基数降到几十万.

技术层处理UHC

kylin通过mapreduce进行此步骤,在reduce端,一个维度用一个reduce去重,因此当某个维度的基数很大时,会导致该维度所在的reduce运行很慢,甚至内存溢出,为了应对这种场景,kylin提供了两种解决方案

1. 全局唯一维度,也就是在count_dintinct中选择0错误率的统计分析。

2. 需要被shard by的维度,在rowkey构建时配置的维度。

接着可以通过配置`kylin.engine.mr.uhc-reducer-count=1`来声明这些列需要被分割成多少个reducer执行

当然,kylin也支持基于cuboid个数来进行reducer个数的分配,`kylin.engine.mr.hll-max-reducer-number=1`,默认情况下kylin不开启此功能,可以修改配置来提高最小个数;然后通过配置`kylin.engine.mr.per-reducer-hll-cuboid-number`来调整具体的reduce数量

int nCuboids = cube.getCuboidScheduler().getAllCuboidIds().size();
int shardBase = (nCuboids - 1) / cube.getConfig().getHadoopJobPerReducerHLLCuboidNumber() + 1; int hllMaxReducerNumber = cube.getConfig().getHadoopJobHLLMaxReducerNumber();
if (shardBase > hllMaxReducerNumber) {
shardBase = hllMaxReducerNumber;
}

最终的reducer数量由UHC和cuboids两个部分相加得到,具体代码参考

`FactDistinctColumnsReducerMapping`构造函数

# 配置UHC增加另外步骤,需要配置zk的地址(作为全局分布式锁使用)

# 因为在跑mapreduce的过程中,kylin没有将hbase-site.xml等配置上传到yarn,所以只能在kylin.properties中额外配置一遍

kylin.engine.mr.build-uhc-dict-in-additional-step=true

kylin.env.zookeeper-connect-string=host:port,host:port

代码 `FactDistinctColumnsJob`, `UHCDictionaryJob`

构建维度字典

找出所有维度的基数后,kyin为每个维度构建一个数据字典,字典的metadata存储在hdfs上,实际数据存储在hbase

字典在hdfs的路径规则为

kylin/kylin_meta_data/kylin-$jobid/%cubeid/metadata/dict/$catalog.$table/$dimension/$uuid.dict

字典数据在hbase的rowkey规则为

/dict/$catalog.$table/$dimension/$uuid.dict

rowkey长度

过长的rowkey会占用很大的存储空间,所以需要对rowkey长度进行控制。

当前kylin直接在当前进程内做了字典编码,也就是把string映射成int,如果维度列的基数很大,那么可能会出现内存溢出的情况(当列的基础大于1kw),这时候就需要考虑更改维度列的编码方式,改用`fixed_length`等。如果一个维度的长度超过`fixed_length`,那么超过的部分会被截断。

rowkey构建

对rowkey的构建也有一定的要求,一般而言,需要把基数大的字段放在前面,这样可以在scan的过程中尽可能的跳过更多的rowkey。

另一方面将基数小的列放在rowkey的后面,可以减少构建的重复计算,有些cuboid可以通过一个以上的父cuboid聚合而成,在这种情况下,Kylin将会选择最小的父cuboid。例如,AB能够通过ABC(id:1110)和ABD(id:1101)聚合生成,因此ABD会被作为父cuboid使用,因为它的id比ABC要小。基于以上处理,如果D的基数很小,那么此次聚合操作就会花费很小的代价。因此,当设计cube的rowkey顺序的时候,请记住,将低基数的维度列放在尾部。这不仅对cube的构建过程有好处,而且对cube查询也有好处,因为后聚合(应该是指在HBase查找对应cuboid的过程)也遵循这个规则。

维度分片

在构建rowkey过程中,有一个选项,可以声明哪个维度用于shard。
这个shard的作用是,将该shard维度和总shard数hash,得到的hash结果插入到encoding后的rowkey中,这样就可以让该维度下相同的数据尽可能的分配到一个shard中,而在hbase存储里,一个shard对应的是一个region,这样处理另一个好处是,在聚合的时候可以很好的把相同数据合并一起,减少网络传输io。参考类`RowKeyEncoder`。一个encoding的rowkey的结构是这样的

head+shard+dim1+dim2+…+dimn

一个segment的总shard数计算方式如下,参考类`CreateHTableJob`,其中,estimatedSize参数类`CubeStatsReader.estimateCuboidStorageSize`

int shardNum = (int) (estimatedSize * magic / mbPerRegion + 1);

因此,声明的shard维度最好是被频繁group by的维度或者是基数很大的维度,这样在coprocess处理的时候可以加速

构建cube

构建引擎

可以选择spark或者mapreduce来构建cube,通常来说,构建引擎的选择方式是这样的

  1. 内存消耗型的cube选择mapreduce,例如Count Distinct, Top-N
  2. 简单的cube选择spark,例如SUM/MIN/MAX/COUNT

spark引擎

spark构建引擎采用` by-layer`算法,也就是分层计算

比如有3个维度ABC,cube会构建A,B,C,AB,AC,ABC6种组合,这里就有3层,

第1层:A,B,C

第2层:AB,AC

第3层:ABC

每一层在计算对于spark而言都是一个action,并且该层计算的rdd会依赖其上一层的结果继续计算,这样避免了很大重复性计算工作。

代码` SparkCubingByLayer`

设计模式

参考《kylin介绍》中的cube设计模式

数据转换为HFile

kylin将生成的cube通过生成HFile的方式导入到hbase,这个优化点可以配置hbase的相关参数。

  1. region数量默认是1,如果数据量大的话可以提高region数量
  2. region大小默认是5GB,也就是hbae官方建议的大小;如果cube大小比这个值小太多,可以减小单region的大小
  3. hfile文件大小,默认是1GB,由于是通过mapreduce写入的,小文件意味着写入快,但是读取慢,大文件意味着写入慢,读取快

代码`CubeHFileJob`

cleanup

  1. 清理hive中的中间表,
  2. 清理hbase表
  3. 清理hdfs数据

清理命令

# 查看需要清理的数据

./bin/kylin.sh org.apache.kylin.tool.StorageCleanupJob --delete false

# 清理

./bin/kylin.sh org.apache.kylin.tool.StorageCleanupJob --delete true

// clean参考

http://kylin.apache.org/docs20/howto/howto_cleanup_storage.html

总结

基于kylin的ui,可以看到kylin在构建cube时各个流程的耗时,可以依据这些耗时做相应的优化,常见的,可以从耗时最长的步骤开始优化,比如:

  1. 遇到创建hive中间表时间很长,考虑对hive表进行分区处理,对表中的文件格式更改,使用orc,parquet等高性能的文件格式
  2. 遇到cube构建时间过长,查看cube设计是否合理,维度的组合关系是否可以再减少,构建引擎是否可以优化

优化的思路还是以cube为中心,优化cube的整个生命周期,其中涉及到的所有组件都是优化点,具体情况还是要和实际的数据维度和业务结合起来。

参考

// 官方文档

http://kylin.apache.org/docs20/howto/howto_optimize_build.html

// 官方文档,cube性能优化

http://kylin.apache.org/docs23/tutorial/cube_build_performance.html

kylin构建cube优化的更多相关文章

  1. Kylin构建Cube过程详解

    1 前言 在使用Kylin的时候,最重要的一步就是创建cube的模型定义,即指定度量和维度以及一些附加信息,然后对cube进行build,当然我们也可以根据原始表中的某一个string字段(这个字段的 ...

  2. Kylin构建cube时状态一直处于pending

    在安装好kylin之后我直接去访问web监控页面发现能够进去,也没有去看日志.然后在运行官方带的例子去bulid cube时去发现状态一直是pending而不是runing.这个时候才去查看日志: 2 ...

  3. Kylin Cube构建过程优化

    原文地址:https://kylin.apache.org/docs16/howto/howto_optimize_build.html Kylin将一个cube的build过程分解为若干个子步骤,然 ...

  4. 调用kylin的restAPI接口构建cube

    调用kylin的restAPI接口构建cube 参考:http://kylin.apache.org/docs/howto/howto_build_cube_with_restapi.html 1. ...

  5. Kylin配置Spark并构建Cube

    HDP版本:2.6.4.0 Kylin版本:2.5.1 机器:三台 CentOS-7,8G 内存 Kylin 的计算引擎除了 MapReduce ,还有速度更快的 Spark ,本文就以 Kylin ...

  6. 《基于Apache Kylin构建大数据分析平台》

    Kyligence联合创始人兼CEO,Apache Kylin项目管理委员会主席(PMC Chair)韩卿 武汉市云升科技发展有限公司董事长,<智慧城市-大数据.物联网和云计算之应用>作者 ...

  7. Kylin Flink Cube 引擎的前世今生

    Apache Kylin™ 是一个开源的.分布式的分析型数据仓库,提供 Hadoop/Spark 之上的 SQL 查询接口及多维分析(OLAP)能力以支持超大规模数据,它能在亚秒内查询巨大的表. Ky ...

  8. 使用Kylin构建企业大数据分析平台的4种部署方式

    本篇博客重点介绍如何使用Kylin来构建大数据分析平台.根据官网介绍,其实部署Kylin非常简单,称为非侵入式安装,也就是不需要去修改已有的 Hadoop大数据平台.你只需要根据的环境下载适合的Kyl ...

  9. 【转】Kylin系列-使用Saiku+Kylin构建多维分析OLAP平台

    关于Kylin的介绍和使用请参考之前的文章 <分布式大数据多维分析(OLAP)引擎Apache Kylin安装配置及使用示例> Kylin对外提供的是SQL查询接口,基于Kylin构建OL ...

随机推荐

  1. python epoll实现异步socket

    一.同步和异步: 在程序执行中,同步运行意味着等待调用的函数.线程.子进程等的返回结果后继续处理:异步指不等待当下的返回结果,直接运行主进程下面的程序,等到有返回结果时,通知主进程处理.有点高效. 二 ...

  2. java定时器学习

    一.这个是利用jdk自带的Thread类的sleep方法实现定时执行任务. package tasker; import java.util.Date; public class tasker01 e ...

  3. 微信小程序 --- 下拉刷新上拉加载

    查看文档看到:page()函数注册页面的时候,有 onPullDownRefresh 监听用户下拉动作,onReachBottom 页面上拉触底事件的函数. 在小程序里,用户顶部下拉是默认禁止的,我们 ...

  4. Hibernate--快速上手

    一.初识 Hibernate 经典的软件应用体系结构有三层:表示层(提供了与用户交互的接口,实现用户操作界面,展示用户需要的数据).业务逻辑层(完成业务流程,处理表示层提交的数据请求,并将要保存的数据 ...

  5. Oracle等待事件之log file parallel write

    log file parallel write表示等待 LGWR 向操作系统请求 I/O 开始直到完成 I/O.这种事件发生通常表示日志文件发生了I/O 竞争或者文件所在的驱动器较慢.这说明这种等待与 ...

  6. The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path(Myeclipse添加Server Library)

    网上找练习的项目导入到myeclipse项目发现每个JSP 出现错误The superclass "javax.servlet.http.HttpServlet" was not ...

  7. python知识大全目录,想学的看过来!

    Python总结篇——知识大全   python装饰器   PyCharm安装与配置,python的Hello World   sort与sorted的区别及实例   我必须得告诉大家的MySQL优化 ...

  8. python分段算利润、税收

    ''' 题目:企业发放的奖金根据利润提成. 利润(I)低于或等于10万元时,奖金可提10%: 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%: 2 ...

  9. drawable转mitmap 以及图片base64编码

    static Bitmap drawableToBitmap(Drawable drawable) // drawable 转换成bitmap { int width = drawable.getIn ...

  10. java, android的aes等加密库

    https://github.com/scottyab/AESCrypt-Android https://github.com/PDDStudio/EncryptedPreferences       ...