1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Kylin - 05 cuboid以及cube优化

Kylin - 05 cuboid以及cube优化

时间:2020-12-20 10:09:24

相关推荐

Kylin - 05 cuboid以及cube优化

Cuboid = one combination of dimensions

Cube = all combination of dimensions (all cuboids)

按照dimension(维度)大小顺序排序,从Base Cuboid开始,依次基于上一层Cuboid的结果进行再聚合。每一层的计算都是一个单独 的Map Reduce(Spark)任务。

理论上来说,一个N维的Cube,便有2的N次方种维度组合,参考网上的一个例子,一个Cube包含time, item, location, supplier四个维度,那么组合(Cuboid)便有16种。

一个Cube中,当维度数量N超过一定数量后,空间以及计算消耗将会非常大,比如说10维那就是1024个cuboid,但我们真正查询的时候可能只会用到其中的100个cuboid,如果不做优化那么会出现以下几个问题

会使得Build出来的Cube Size 很大,从而占用大量的磁盘空间;Cube Building的时间会很长 ;会占用集群的计算资源 。

5.1 Cube剪枝优化

5.1.1 聚合组Aggravation Group

Kylin在定义Cube时候,可以将维度拆分成多个聚合组(Aggregation Groups)这也就是我们在web页面创建cube时的第5步可以做,只在组内计算Cube,聚合组内查询效率高,跨组查询效率较差,所以需要根据业务场景,将常用的维度组合定义到一个聚合组中,提高查询性能,这也是Kylin中查询性能优化的一个重要方面。

举例:

业务场景有4个维度,分别为ABCD,如果聚合组含有的维度为ABCD的话,它的Cuboid为2 ^ 4 =16个。但是此时如果AB是一个聚合组,CD是一个聚合组,那么Cuboid的个数就是 2^2 + 2^2 =8个,相当于缩减了一半。即原来2 ^ (K+M+N)个Cuboid可以减少到2^K + 2^M + 2^N个。

查看cube所生成的cuboid个数命令如下:

kylin.sh org.apache.kylin.mon.CubeStatsReader CubeName

5.1.1.1 强制维度(Mandatory Dimensions)

如果一个维度被定义为强制维度,那么这个分组产生的所有Cuboid中每一个Cuboid都会包含该维度。如果根据这个分组的业务逻辑,相关的查询一定会在过滤条件或分组条件中,则可以在该分组中把该维度设置为强制维度。

5.1.1.2 层次维度(Hierarchy Dimensions)

何为层次维度,具有上下级层次关系的维度,例如时间维度 年—>月—>日,和地区维度 国家(country)—>省份(province)—> 城市(city)。将有这样关系的维度设置为层次关系,并且将它们设置为层次维度的话,cuboid数量将下降。

举例:

如果有三个维度A,B,C 设置为层次维度,那么Cuboid数量将由2^3减为3+1(ABC、AB、A、空)。

对应的group by就变成了如下三种情况

group by country, province, city(等同于 group by country, city 或者group by city)

group by country, province(等同于group by province)

group by country。

Hive里面的数据以时间作为分区,每天处理增量数据,那么我们kylin也要每天增量写入数据。

5.1.1.3 联合维度(Joint Dimensions)

每个联合中包含两个或更多个维度,如果某些列形成一个联合,那么在该分组产生的任何Cuboid中,这些联合维度要么一起出现,要么都不出现。如果根据这个分组的业务逻辑,多个维度在查询中总是同时出现,则可以在该分组中把这些维度设置为联合维度。

例子:如有 A B C D 四个维度, B C维度作为联合维度,则最后只要生成7个维度,如下图所示:其中红色维度为无需生成的维度,黑色维度为需要生成的维度

5.1.2 衍生维度

时间维度表,里面充斥着用途各异的时间维度,例如每个日期所处的季度、月份等。这些维度可以被地用来进行各个时间粒度上的聚合分析,而不需要进行额外的上卷(Roll Up)操作。但是为了这个目的一下子引入这么多个维度,导致 Cube中总共的Cuboid数量呈现爆炸式的增长往往是得不偿失的。

当用户需要以更高的粒度(比如按周、 按月)来聚合时,如果在查询时获取按日聚合的Cuboid数据,并在查询引擎中实时地进行上卷操作,那么就达到了使用牺牲一部分运行时性能来节省Cube空间占用的目的。

Kylin将这样的理念包装成为了一个简单的优化工具——衍生维度。

衍生维度用于在有效维度内将维度表上的非主键维度排除掉,并使用维度表的主键(其实是事实表上相应的外键)来替代它们。Kylin会在底层记录维度表主键与维度表其他维度之间的映射关系,以便在查询时能够动态地将维度表的主键“翻译”成这些非主键维度,并进行实时聚合。

例如,假设有一个日期查找表,其中的cal_dt是主键列,还有许多派生列,例如week_begin_dt,month_begin_dt。即使分析人员需要week_begin_dt作为维度,我们也可以对其进行修剪,因为它始终可以从cal_dt维度进行计算,这是“派生”优化。

5.2 Rowkey编码优化

编码(Encoding)代表了该维度的值应使用何种方式进行编码,合适的编码能够减少维度对空间的占用,例如,我们可以把所有的日期都用三个字节进行编码,相比于字符串存储,或者是使用长整数形式存储的方法,我们的编码方式能够大大减少每行Cube数据的体积。而Cube中可能存在数以亿计的行数,使用编码节约的空间累加起来将是一个非常巨大的数字。00000101

目前Kylin支持的编码方式有以下几种:

Date编码:将日期类型的数据使用三个字节进行编码,其支持从 0000-01-01到9999-01-01中的每一个日期。Time编码:仅支持表示从1970-01-01 00:00:00到2038-01-19 03:14:07的时间,且Time-stamp类型的维度经过编码和反编码之后,会失去毫秒信息,所以说Time编码仅仅支持到秒。但是Time编码的优势是每个维度 仅仅使用4个字节,这相比普通的长整数编码节约了一半。如果能够接受秒级的时间精度,请选择Time编码来代表时间的维度。Integer编码:Integer编码需要提供一个额外的参数“Length”来代表需 要多少个字节。Length的长度为1~8。如果用来编码int32类型的整数,可以将Length设为4;如果用来编码int64类型的整数,可以将Length设为8。在更多情况下,如果知道一个整数类型维度的可能值都很小,那么就能使用 Length为2甚至是1的int编码来存储,这将能够有效避免存储空间的浪费。Dict编码:对于使用该种编码的维度,每个Segment在构建的时候都会为这个维度所有可能的值创建一个字典,然后使用字典中每个值的编 号来编码。Dict的优势是产生的编码非常紧凑,尤其在维度值的基数较小且长度较大的情况下,特别节约空间。由于产生的字典是在查询时加载入构建引擎和查询引擎的,所以在维度的基数大、长度也大的情况下,容易造成构建引擎或查询引擎的内存溢出。Fixed_length编码:编码需要提供一个额外的参数“Length”来代表需 要多少个字节。该编码可以看作Dict编码的一种补充。对于基数大、长度 也大的维度来说,使用Dict可能不能正常工作,于是可以采用一段固定长度的字节来存储代表维度值的字节数组,该数组为字符串形式的维度值的UTF-8字节。如果维度值的长度大于预设的Length,那么超出的部分将会被截断。Fixed_Length_Hex编码: 适用于字段值为十六进制字符,比如1A2BFF或者FF00FF,每两个字符需要一个字节。只适用于varchar或nvarchar类型。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。