当前位置:   article > 正文

kylin学习(四) -- cube构建优化(剪枝优化)_kylin剪枝

kylin剪枝

1.前言

从之前章节的介绍可以知道,在没有采取任何优化措施的情况下,Kylin会对每一种维度的组合进行预计算,每种维度的组合的预计算结果被称为Cuboid。假设有4个维度,我们最终会有24 =16个Cuboid需要计算。
但在现实情况中,用户的维度数量一般远远大于4个。假设用户有10 个维度,那么没有经过任何优化的Cube就会存在210 =1024个Cuboid;而如果用户有20个维度,那么Cube中总共会存在220 =1048576个Cuboid。虽然每个Cuboid的大小存在很大的差异,但是单单想到Cuboid的数量就足以让人想象到这样的Cube对构建引擎、存储引擎来说压力有多么巨大。因此,在构建维度数量较多的Cube时,尤其要注意Cube的剪枝优化(即减少Cuboid的生成)
比如维度是年月日,我们可能以年、年月、年月日去分析,不会以年日去分析;这个年日的cuboid就是多余的不需要计算的。

2. 使用衍生维度(derived dimension)

2.1 在kylin中的操作:

  1. 我们添加4个维度,按道理应该有2^4 -1 = 15个cuboid
    在这里插入图片描述
  2. 但是我们最后去planner中可以看到,只有7个cuboid

在这里插入图片描述

2.2 理念:

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

如图:
事实表A和维度表B,共有A,B,E三个维度,共计7个cuboid;如果A和E存在某种联系:A能找到D,D能找到E的时候,可以用A代替E来减少cuboid数量。
在这里插入图片描述

2.3使用场景:

虽然衍生维度具有非常大的吸引力,但这也并不是说所有维度表上的维度都得变成衍生维度,如果从维度表主键到某个维度表维度所需要的聚合工作量非常大,则不建议使用衍生维度(比如一对多的关系,多这边的数据量相当庞大时(年月日中的日))。
虽然减少了计算量,空间占用少了,但是由于最后需要聚合,浪费了时间,是一种一时间换空间的做法

如图:

  1. 根据事实表和维度表,生成了中间表,同时找到在A和E对应关系,比如假设A是商品订单id,B是下单地区id,C是订单金额,E是地区名称,现在需要统计各地区销售额
  2. 构建cube时,我们可以用A代替E来减少cuboid提高查询效率
  3. 查询时,我们根据A和E的对应关系,用E替换A
  4. 获取结果时,由于E可能有重复数据,那我们需要将数据聚合后再展示

在这里插入图片描述

3. 使用聚合组(Aggregation group)

3.1 理念:

聚合组(Aggregation Group)是一种强大的剪枝工具。聚合组假设一个Cube的所有维度均可以根据业务需求划分成若干组(当然也可以是一个组),由于同一个组内的维度更可能同时被同一个查询用到,因此会表现出更加紧密的内在关联。每个分组的维度集合均是Cube所有维度的一个子集,不同的分组各自拥有一套维度集合,它们可能与其他分组有相同的维度,也可能没有相同的维度。每个分组各自独立地根据自身的规则贡献出一批需要被物化的Cuboid,所有分组贡献的Cuboid的并集就成为了当前Cube中所有需要物化的Cuboid的集合。不同的分组有可能会贡献出相同的Cuboid,构建引擎会察觉到这点,并且保证每一个Cuboid无论在多少个分组中出现,它都只会被物化一次。
对于每个分组内部的维度,用户可以使用如下三种可选的方式定义,它们之间的关系:

  • 强制维度
  • 层级维度
  • 联合维度

3.2 强制维度(Mandatory):

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

如图:如果将A设置为强制维度,那么只会生成包含A的cuboid
在这里插入图片描述

3.3 层级维度(Hierarchy):

每个层级包含两个或更多个维度。假设一个层级中包含D1,D2…Dn这n个维度,那么在该分组产生的任何Cuboid中, 这n个维度只会以(),(D1),(D1,D2)…(D1,D2…Dn)这n+1种形式中的一种出现。每个分组中可以有0个、1个或多个层级,不同的层级之间不应当有共享的维度。如果根据这个分组的业务逻辑,则多个维度直接存在层级关系,因此可以在该分组中把这些维度设置为层级维度。
比如省市县,只会以省,省市,省市县出现,不会单独出现市、县。

如图,有A、B、C三个维度,如果设置了层级维度A->那么可以单独出现A,不能单独出现B,B必须和A绑定出现
在这里插入图片描述

3.4 联合维度(Joint):

每个联合中包含两个或更多个维度,如果某些列形成一个联合,那么在该分组产生的任何Cuboid中,这些联合维度要么一起出现,要么都不出现。每个分组中可以有0个或多个联合,但是不同的联合之间不应当有共享的维度(否则它们可以合并成一个联合)。如果根据这个分组的业务逻辑,多个维度在查询中总是同时出现,则可以在该分组中把这些维度设置为联合维度。
在这里插入图片描述

3.5 kylin中使用:

这些操作可以在Cube Designer的Advanced Setting中的Aggregation Groups区域完成,如下图所示。
其中层级维度(Hierarchy)是按照先后顺序作为层级关系。比如选择了AB,层级关系就是A -> B
在这里插入图片描述

聚合组的设计非常灵活,甚至可以用来描述一些极端的设计。假设我们的业务需求非常单一,只需要某些特定的Cuboid,那么可以创建多个聚合组,每个聚合组代表一个Cuboid。具体的方法是在聚合组中先包含某个Cuboid所需的所有维度,然后把这些维度都设置为强制维度。这样当前的聚合组就只能产生我们想要的那一个Cuboid了。
再比如,有的时候我们的Cube中有一些基数非常大的维度,如果不做特殊处理,它就会和其他的维度进行各种组合,从而产生一大堆包含它的Cuboid。包含高基数维度的Cuboid在行数和体积上往往非常庞大,这会导致整个Cube的膨胀率变大。如果根据业务需求知道这个高基数的维度只会与若干个维度(而不是所有维度)同时被查询到,那么就可以通过聚合组对这个高基数维度做一定的“隔离”。我们把这个高基数的维度放入一个单独的聚合组,再把所有可能会与这个高基数维度一起被查询到的其他维度也放进来。这样,这个高基数的维度就被“隔离”在一个聚合组中了,所有不会与它一起被查询到的维度都没有和它一起出现在任何一个分组中,因此也就不会有多余的Cuboid产生。这点也大大减少了包含该高基数维度的Cuboid的数量,可以有效地控制Cube的膨胀率。

4. Row Key优化

Kylin会把所有的维度按照顺序组合成一个完整的Rowkey,并且按照这个Rowkey升序排列Cuboid中所有的行。
设计良好的Rowkey将更有效地完成数据的查询过滤和定位,减少IO次数,提高查询速度,维度在rowkey中的次序,对查询性能有显著的影响。
Row key的设计原则如下:

4.1 被用作where过滤的维度放在前边。

假设查询条件是以B为主,设计维度的时候,如果先选A,再选B会降低查询效率,如果先选B再选A,可以大大提高查询效率
在这里插入图片描述

4.2 基数大的维度放在基数小的维度前边。

假设有4个维度,最后想要使用AB两个维度,在使用分层计算时:

  1. 第一步先计算四个维度的1111
  2. 计算三个维度的,同时包含AB两个维度的,那就是1110和1101,
  3. 计算1100,这时,MR会选择数值小的作为原始数据查询AB的数据,也就是从1101中查到1100的数据(因为1110 > 1101)
  4. 这时,假如D的基数很大,就会增加我们的计算量;而如果数量量大的是C,数量量小的是D,如下图左下和右下表格,那儿我们就会从数据量少的数据中计算出AB的数据,而不是数据量大的。所以我们尽量将数据量大的维度放在前面

在这里插入图片描述

4.3 kylin中使用:

可以直接点中行上下拖动
在这里插入图片描述

5. 并发粒度优化

当Segment中某一个Cuboid的大小超出一定的阈值时,系统会将该Cuboid的数据分片到多个分区中,以实现Cuboid数据读取的并行化,从而优化Cube的查询速度。具体的实现方式如下:构建引擎根据Segment估计的大小,以及参数“kylin.hbase.region.cut”的设置决定Segment在存储引擎中总共需要几个分区来存储,如果存储引擎是HBase,那么分区的数量就对应于HBase中的Region数量。kylin.hbase.region.cut的默认值是5.0,单位是GB,也就是说对于一个大小估计是50GB的Segment,构建引擎会给它分配10个分区。用户还可以通过设置kylin.hbase.region.count.min(默认为1)和kylin.hbase.region.count.max(默认为500)两个配置来决定每个Segment最少或最多被划分成多少个分区。
在这里插入图片描述

由于每个Cube的并发粒度控制不尽相同,因此建议在Cube Designer 的Configuration Overwrites(上图所示)中为每个Cube量身定制控制并发粒度的参数。假设将把当前Cube的kylin.hbase.region.count.min设置为2,kylin.hbase.region.count.max设置为100。这样无论Segment的大小如何变化,它的分区数量最小都不会低于2,最大都不会超过100。相应地,这个Segment背后的存储引擎(HBase)为了存储这个Segment,也不会使用小于两个或超过100个的分区。我们还调整了默认的kylin.hbase.region.cut,这样50GB的Segment基本上会被分配到50个分区,相比默认设置,我们的Cuboid可能最多会获得5倍的并发量。

6. 增量构建(不属于构建优化,属于内存优化)

第一步:model中指定分区列

可以设置每天或者每月的数据生成一个cube数据
设置哪张表的哪个列的哪种事件类型分区。(has a separate。。。代表如果时间被分成了2个字段的话,就设置两个列来区分)
在这里插入图片描述

第二步:cube中合并cube(不一定需要)

如果cube是按照每天生成数据,那么可以设置将每周的7个cube或者每一个月的数据合并成一个大的cube。

如图Auto Merge Theresholds设置了每7天,攒了7个一天的cube1后合成一次数据生成cube2,然后每28天,也就是4周后,将4个cube2合成一次数据生成cube3.
在这里插入图片描述

第三步:指定合并开始时间(不一定需要)

如上图Partition Start Date,可以指定合并开始的日期

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/697598
推荐阅读
  

闽ICP备14008679号