前言

Apache Kylin 在中企的使用主要在新数仓系统以及 BI 报表的数据计算工作,带来的变化有:

一方面Kylin帮助我们提升了开发效率,减少了开发人员需要手动编写HQL/SQL 语句去查询维度数据的状况;

另一方面解耦现有系统设计,数据计算层主要包括Spark类的实时计算和HQL的离线计算(Kylin在我司目前还没有接入实时流计算,后期会尝试接入),通过引入Kylin,整个离线计算这一块就可以转到Kylin去处理,灵活度高了很多;

最后,Apache Kylin采用HBase做为结果集的存储,对外提供API,并且支持大部分BI展示工具,目前2.0+版本也提供了基于Spark的计算引擎和雪花模型,可见,在未来Kylin在中企动力的应用场景会越来越丰富。

在Apache Kylin高性能的背后,Cube是至关重要的核心。Cube是所有Dimension 的组合,每一种Dimension 的组合称之为Cuboid,有N个Dimension的Cube就会有2^n个Cuboid。因此,一个优化得当的Cube既能满足高速查询的需要,又可节省集群资源,本文将从Kylin Cube的设计方面带大家了解Cube的优化方案。

为何需要优化Cube?

前面说过,Cube是所有维度的组合,当我们有10个维度时,那么就会预计算2^10 也就是1024个Cuboid,但当我们真正查询的时候,可能只会用到100个Cuboid,如果不对Cube进行优化的话:

  • 会使得Build出来的Cube Size 很大,从而占用大量的磁盘空间;

  • Cube Building的时间会很长 ;

  • 会占用集群的计算资源 。

因此,如果使用Apache Kylin做数据分析,Cube优化将是我们必做的一项工作。

Cube 维度优化主要方式

1. Cube ID 剪枝优化

2. 衍生维度优化

3. 聚合组优化

4.  强制维度

5.  层次维度

6.  联合维度

7.  Cube并发粒度优化

以上7种优化方式,都可以认为是对维度的一种剪枝,因为每种优化的最终目的都是为了减少Cuboid的数量,下面我将逐个介绍每个优化项的概念以及使用场景。

1. Cube ID 剪枝优化

前面说到如果有10个维度,那么就会生成2^10=1024个Cuboid,如果有20个维度那么将会生成2^20=1048576个Cuboid,是指数级增长,kylin.properties中参数 kylin.cube.aggrgroup.max-combination=4096,也就是说当Cuboid数量大于4096时, Cube定义是无法保存的的,会报TooManyCuboidException异常。

1.检查Cuboid数目

执行命令 :

bin/kylin.sh org.apache.kylin.engine.mr.common.CubeStatsReader cubeName

2.检查Cube Size

在kylin web gui 的model界面选择一个READY状态的Cube,将光标移到Cube Size上面,会显示出Cube源数据的大小,以及当前Cube的大小除以源数据大小的比例,如图:

一般,Cube的膨胀率应该在0%-1000%之间,如果Cube的膨胀率超过了1000%,那么就需要查询其中的原因了,导致膨胀率高的原因一般为以下几点:

1)、Cube的维度数量较多,没有进行很好的剪枝;

2)、Cube中存在较高基数的维度,导致这类维度每个Cuboid占用的空间很大,从而造成Cube体积变大;

3)、存在比较占用空间的度量。

对于Cube膨胀率高的情况,需要针对实际的业务需求进行分析,可以考虑通过下面的几种优化方式进行优化:

2. [Derived Dim]衍生维度优化

衍生维度(Derived Dim):当一个或者多个维度能够从主键中推断出来,那么这些维度列就称之为衍生“Derived” 列。

衍生维度(Derived Dim)优化效果:维度表中的n个维度计算,将Cuboid从2^n 减为2。

使用场景:在星型模型中,有一个用户维度表,表中包含了ID,A,B,C ,其中ID 为PK,在这里通过ID的值就可以确定A,B,C的值,因为A,B,C为ID的Derived。当进行build一个Cube包含A,B,C 的时候,只需要包含ID,并且将A,B,C标记为derived ,这样derived列就不会生成Cuboid 。

3. [Aggregation Group]聚合组优化

聚合组(Aggregation Group): 根据业务的维度组合,划分出具有强依赖的组合,这些组合称之为聚合组,在聚合组内,维度之间的组合会预计算,聚合组之间并不交叉预计算,从而减少Cuboid的数量.

聚合组优化效果:如果有4个维度,分别为A,B,C,D,那么就会有16个Cuboid,如果AB和CD分别为聚集组的话,那么Cuboid的数量就缩减为8个。

使用场景:所有维度中,有部分维度之间具有聚合操作的,可以将这些维度放在一个聚合组内。不放在聚合组里面的,就直接进行Base Cube操作。

4. [Mandatory Dimensions]强制维度

强制维度(Mandatory Dimensions):所有Cubeid中都包含的维度称之为强制维度,不包含强制维度的Cubeid不会计算。

优化效果:只计算包含强制维度的Cubeid,Cubeid的数量会缩减一半。

使用场景:假如有三个维度A,B,C,那么Cuboid就会有8个,分别为ABC,AB,BC,AC,A,B,C,这时将A设置为强制维度,那么就只会计算ABC,AB,AC,A这四个 Cubeid。

5. [Hierarchy Dimension]层次维度

层次维度(Hierarchy Dim):某些维度之间具有上下层次关联。

优化效果:如果有三个维度A,B,C 设置为层次维度,那么Cuboid数量将由2^3减为3+1。

使用场景:比较适用于进行下钻分析,比如年月日,省市县这种。

6. [Joint Dimension]联合维度

联合维度(Joint Dimension):固定用来分组的维度查询。

优化效果:将多个维度优化到一个维度。

使用场景:假如有ABC三个维度,但是在查询的时候只会出现Group by A,B,C,而不会出现Group A,Group by B,Group by A、B等等这种情况,那么就可以将A,B,C设置为联合维度。

7. 调整Cube并发粒度

当Segment中某个Cuboid的大小超出一定的阈值时,系统会将该Cuboid的数据分片到多个Hbase Region Server,从而实现Cuboid数据读取的并行化,优化Cube的查询速度。

kylin的默认设置中

kylin.storage.hbase.region-cut-gb=5,

kylin.storage.hbase.min-region-count=1,

kylin.storage.hbase.max-region-count=500

在实际应用中(根据实际数据量调整),可以将

kylin.storage.hbase.min-region-count=2,

kylin.storage.hbase.max-region-count=100,

kylin.storage.hbase.region-cut-gb=1

上面设置为最小为2个分区,每个分区大小为1G,最多设置100个region分区