kylin高级设置

更新设置 refresh settings

这一步骤是为增量构建 cube 而设计的。

Auto Merge Thresholds: 自动合并小的 segments 到中等甚至更大的 segment。如果不想自动合并,删除默认2个选项。

Volatile Range: 默认为0,会自动合并所有可能的 cube segments,或者用 ‘Auto Merge’ 将不会合并最新的 [Volatile Range] 天的 cube segments。

Retention Threshold: 只会保存 cube 过去几天的 segment,旧的 segment 将会自动从头部删除;0表示不启用这个功能。

Partition Start Date: cube 的开始日期.

高级设置 advanced settings

说明:

Aggregation Groups: Cube 中的维度可以划分到多个聚合组中。默认 kylin 会把所有维度放在一个聚合组,当维度较多时,产生的组合数可能是巨大的,会造成 Cube 爆炸;如果你很好的了解你的查询模式,那么你可以创建多个聚合组。在每个聚合组内,使用 “Mandatory Dimensions”, “Hierarchy Dimensions” 和 “Joint Dimensions” 来进一步优化维度组合。

Mandatory Dimensions: 必要维度,用于总是出现的维度。例如,如果你的查询中总是会带有 “ORDER_DATE” 做为 group by 或 过滤条件, 那么它可以被声明为必要维度。这样一来,所有不含此维度的 cuboid 就可以被跳过计算。(比如,Mandatory Dimensions设置为p1,所有不包含该维度p1的cuboid会被跳过计算,当我们查询select channeled, count(*) from soda_report where datetime=’20180919’ group by channeled时,没有现成的完全匹配的 Cuboid,Kylin 会通过在线计算的方式,从现有的 Cuboid 中计算出最终结果)

Hierarchy Dimensions: 层级维度,例如 “国家” -> “省” -> “市” 是一个层级;不符合此层级关系的 cuboid 可以被跳过计算,例如 [“省”], [“市”]. 定义层级维度时,将父级别维度放在子维度的左边。

Joint Dimensions: 联合维度,有些维度往往一起出现,或者它们的基数非常接近(有1:1映射关系)。例如 “user_id” 和 “email”。把多个维度定义为组合关系后,所有不符合此关系的 cuboids 会被跳过计算。

ROWKEYS

是由维度编码值组成。”Dictionary” (字典)是默认的编码方式; 字典只能处理中低基数(少于一千万)的维度;如果维度基数很高(如大于1千万), 选择 “false” 然后为维度输入合适的长度,通常是那列的最大长度值; 如果超过最大值,会被截断。请注意,如果没有字典编码,cube 的大小可能会非常大。

你可以拖拽维度列去调整其在 rowkey 中位置; 位于rowkey前面的列,将可以用来大幅缩小查询的范围。通常建议将 mandantory 维度放在开头, 然后是在过滤 ( where 条件)中起到很大作用的维度;如果多个列都会被用于过滤,将高基数的维度(如 user_id)放在低基数的维度(如 age)的前面。

Mandatory Cuboids: 

维度组合白名单。确保你想要构建的 cuboid 能被构建。

Cube Engine: 

cube 构建引擎。有两种:MapReduce 和 Spark。如果你的 cube 只有简单度量(SUM, MIN, MAX),建议使用 Spark。如果 cube 中有复杂类型度量(COUNT DISTINCT, TOP_N),建议使用 MapReduce。

Advanced Dictionaries:

“Global Dictionary” 是用于精确计算 COUNT DISTINCT 的字典, 它会将一个非 integer的值转成 integer,以便于 bitmap 进行去重。如果你要计算 COUNT DISTINCT 的列本身已经是 integer 类型,那么不需要定义 Global Dictionary。 Global Dictionary 会被所有 segment 共享,因此支持在跨 segments 之间做上卷去重操作。请注意,Global Dictionary 随着数据的加载,可能会不断变大。

“Segment Dictionary” 是另一个用于精确计算 COUNT DISTINCT 的字典,与 Global Dictionary 不同的是,它是基于一个 segment 的值构建的,因此不支持跨 segments 的汇总计算。如果你的 cube 不是分区的或者能保证你的所有 SQL 按照 partition_column 进行 group by, 那么你应该使用 “Segment Dictionary” 而不是 “Global Dictionary”,这样可以避免单个字典过大的问题。

请注意:”Global Dictionary” 和 “Segment Dictionary” 都是单向编码的字典,仅用于 COUNT DISTINCT 计算(将非 integer 类型转成 integer 用于 bitmap计算),他们不支持解码,因此不能为普通维度编码。

Advanced Snapshot Table: 

为全局 lookup 表而设计,提供不同的存储类型。

Advanced ColumnFamily:

 如果有超过一个的COUNT DISTINCT 或 TopN 度量, 你可以将它们放在更多列簇中,以优化与HBase 的I/O。

配置重写 configuration Overwrites

说明:Kylin允许在Cube级别覆盖部分kylin.properties中的配置,你可以在这里定义覆盖的属性,如果不需要,则Next

管理cube碎片

增量构建的Cube每天都可能会有新的增量。日积月累,这样的Cube中最终可能包含上百个Segment,这将会导致查询性能受到严重的影响,因为运行时的查询引擎需要聚合多个Segment的结果才能返回正确的查询结果。从存储引擎的角度来说,大量的Segment会带来大量的文件,这些文件会充斥所提供的命名空间,给存储空间的多个模块带来巨大的压力,例如Zookeeper、HDFS Namenode等。因此,有必要采取措施控制Cube中Segment的数量。

另外,有时候用户场景并不能完美地符合增量构建的要求,由于ETL过程存在延迟,数据可能一直在持续地更新,有时候用户不得不在增量更新已经完成后又回过头来刷新过去已经构建好了的增量Segment,对于这些问题,需要在设计Cube的时候提前进行考虑。

3.4.1 合并Segment

Kylin提供了一种简单的机制用于控制Cube中Segment的数量:合并Segments。在Web GUI中选中需要进行Segments合并的Cube,单击Action→Merge,然后在对话框中选中需要合并的Segment,可以同时合并多个Segment,但是这些Segment必须是连续的。单击提交后系统会提交一个类型为“MERGE”的构建任务,它以选中的Segment中的数据作为输入,将这些Segment的数据合并封装成为一个新的Segment(如图3-5所示)。这个新的Segment的起始时间为选中的最早的Segment的起始时间,它的结束时间为选中的最晚的Segment的结束时间。

 

图3-5 合并Segment

在MERGE类型的构建完成之前,系统将不允许提交这个Cube上任何类型的其他构建任务。但是在MERGE构建结束之前,所有选中用来合并的Segment仍然处于可用的状态。当MERGE构建结束的时候,系统将选中合并的Segment替换为新的Segment,而被替换下的Segment等待将被垃圾回收和清理,以节省系统资源。

用户也可以使用Rest接口触发合并Segments,该API在之前的触发增量构建中也已经提到过:

PUT https://hostname:port/kylin/api/Cubes/{CubeName}/rebuild

 

Path Variable

CubeName – 必须的,Cube名字

Request Body

startTime – 必须的,长整数类型的起始时间,例如使用1388563200000代表起始时间为2014-01-01

endTime – 必须的,长整数类型的结束时间

buildType – 必须的,构建类型,可能的值为‘BUILD’‘MERGE’和‘REFRESH’,分别对应于新建Segment、合并多个Segment,以及刷新某个Segment

我们需要将buildType设置为MERGE,并且将startTime设置为选中的需要合并的最早的Segment的起始时间,将endTime设置为选中的需要合并的最晚的Segment的结束时间。

合并Segment非常简单,但是需要Cube管理员不定期地手动触发合并,尤其是当生产环境中存在大量的Cube时,对每一个Cube单独触发合并操作会变得非常繁琐,因此,Kylin也提供了其他的方式来管理Segment碎片。

3.4.2 自动合并

在3.2.2节中曾提到过,在Cube Designer的“Refresh Settings”的页面中有“Auto Merge Thresholds”和“Retention Threshold”两个设置项可以用来帮助管理Segment碎片。虽然这两项设置还不能完美地解决所有业务场景的需求,但是灵活地搭配使用这两项设置可以大大减少对Segment进行管理的麻烦。

“Auto Merge Thresholds”允许用户设置几个层级的时间阈值,层级越靠后,时间阈值就越大。举例来说,用户可以为一个Cube指定(7天、28天)这样的层级。每当Cube中有新的Segment状态变为READY的时候,就会触发一次系统试图自动合并的尝试。系统首先会尝试最大一级的时间阈值,结合上面的(7天、28天)层级的例子,首先查看是否能将连续的若干个Segment合并成为一个超过28天的大Segment,在挑选连续Segment的过程中,如果遇到已经有个别Segment的时间长度本身已经超过了28天,那么系统会跳过该Segment,从它之后的所有Segment中挑选连续的累积超过28天的Segment。如果满足条件的连续Segment还不能够累积超过28天,那么系统会使用下一个层级的时间阈值重复寻找的过程。每当找到了能够满足条件的连续Segment,系统就会触发一次自动合并Segment的构建任务,在构建任务完成之后,新的Segment被设置为READY状态,自动合并的整套尝试又需要重新再来一遍。

举例来说,如果现在有A~H 8个连续的Segment,它们的时间长度分别为28天(A)、7天(B)、1天(C)、1天(D)、1天(E)、1天(F)、1天(G)、1天(H)。此时第9个Segment I加入,它的时间长度为1天,那么现在Cube中总共存在9个Segment。系统首先尝试能否将连续的Segment合并到28天这个阈值上,由于Segment A已经超过28天,它会被排除。接下来的B到H加起来也不足28天,因此第一级的时间阈值无法满足,退一步系统尝试第二级的时间阈值,也就是7天。系统重新扫描所有的Segment,发现A和B已经超过7天,因此跳过它们,接下来发现将Segment C到I合并起来可以达到7天的阈值,因此系统会提交一个合并Segment的构建请求,将Segment C到I合并为一个新的Segment X。X的构建完成之后,Cube中只剩下三个Segment,分别是原来的A(28天),B(7天)和新的X(7天)。由于X的加入,触发了系统重新开始整个合并尝试,但是发现已经没有满足自动合并的条件,既没有连续的、满足条件的、累积超过28天的Segment,也没有连续的、满足条件的、累积超过7天的Segment,尝试终止。

再举一个例子,如果现在有A~J 10个连续的Segment,它们的时间长度分别为28天(A)、7天(B)、7天(C)、7天(D)、1天(E)、1天(F)、1天(G)、1天(H)、1天(I)、1天(J)。此时第11个Segment K加入,它的时间长度为1天,那么现在Cube中总共存在11个Segment。系统首先尝试能否将连续的Segment合并到28天这个阈值上,由于Segment A已经超过28天,它会被排除。系统接着从Segment B开始观察,发现若把Segment B至K这10个连续的Segment合并在一起正好可以达到第一级的阈值28天,因此系统提交一个合并构建任务把B至K合并为一个新的Segment X,最终Cube中存在两个长度均为28天的Segment,依次对应原来的A和新的X。由于X的加入,触发了系统重新开始整个合并尝试,但是发现已经没有满足自动合并的条件,尝试终止。

“Auto Merge Thresholds”的设置非常简单,在Cube Designer的“Refresh Setting”中,单击“Auto Merge Thresholds”右侧的“New Thresholds”按钮,即可在层级的时间阈值中添加一个新的层级,层级一般按照升序进行排列(如图3-6所示)。从前面的介绍中不难得出结论,除非人为地增量构建一个非常大的Segment,自动合并的Cube中,最大的Segment的时间长度等于层级时间阈值中最大的层级。也就是说,如果层级被设置为(7天、28天),那么Cube中最长的Segment也不过是28天,不会出现横跨半年甚至一年的大Segment。

在一些场景中,用户可能更希望系统能以自然日的星期、月、年作为单位进行自动合并,这样在只需要查询个别月份的数据时,就能够只访问该月的Segment,而非两个毗邻的28天长度的Segment。对此,https://issues.apache.org/jira/browse/KYLIN-1865 记录了这个问题。

 

图3-6 设置自动合并阈值

3.4.3 保留Segment

从碎片管理的角度来说,自动合并是将多个Segment合并为一个Segment,以达到清理碎片的目的。保留Segment则是从另外一个角度帮助实现碎片管理,那就是及时清理不再使用的Segment。在很多业务场景中,只会对过去一段时间内的数据进行查询,例如对于某个只显示过去1年数据的报表,支撑它的Cube事实上只需要保留过去一年内的Segment即可。由于数据在Hive中往往已经存在备份,因此无需再在Kylin中备份超过一年的历史数据。

在这种情况下,我们可以将“Retention Threshold”设置为365。每当有新的Segment状态变为READY的时候,系统会检查每一个Segment:如果它的结束时间距离最晚的一个Segment的结束时间已经大于“Retention Threshold”,那么这个Segment将被视为无需保留。系统会自动地从Cube中删除这个Segment。

如果启用了“Auto Merge Thresholds”,那么在使用“Retention Threshold”的时候需要注意,不能将“Auto Merge Thresholds”的最大层级设置得太高。假设我们将“Auto Merge Thresholds”的最大一级设置为1000天,而将“Retention Threshold”设置为365天,那么受到自动合并的影响,新加入的Segment会不断地被自动合并到一个越来越大的Segment之中,糟糕的是,这会不断地更新这个大Segment的结束时间,从而导致这个大Segment永远不会得到释放。因此,推荐自动合并的最大一级的时间不要超过1年。

3.4.4 数据持续更新

在实际应用场景中,我们常常会遇到这样的问题:由于ETL过程的延迟,业务每天都需要刷新过去N天的Cube数据。举例来说,客户有一个报表每天都需要更新,但是每天的源数据更新不仅包含了当天的新数据,还包括了过去7天内数据的补充。一种比较简单的方法是,每天在Cube中增量构建一个长度为一天的Segment,这样过去7天的数据就会以7个Segment的形式存在于Cube之中。Cube的管理员除了每天要创建一个新的Segment代表当天的新数据(BUILD操作)以外,还需要对代表过去7天的7个Segment进行刷新(REFRESH操作,Web GUI上的操作及Rest API参数与BUILD类似,这里不再详细展开)。这样的方法固然可以奏效,但是每天为每个Cube触发的构建数量太多,容易造成Kylin的任务队列堆积大量未能完成的任务。

上述简单方案的另外一个弊端是,每天一个Segment也会让Cube中迅速地累积大量的Segment,需要Cube管理员手动地对历史已经超过7天的Segment进行合并,期间还必须小心翼翼地,不能错将7天内的Segment一起合并了。举例来说,假设现在有100个Segment,每个Segment代表过去的一天的数据,Segment按照起始时间排序。在合并时,我们只能挑选前面93个Segment进行合并,如果不小心把第94个Segment也一起合并了,那么当我们试图刷新过去7天(94~100)的Segment的时候,会发现为了刷新第94天的数据,不得不将1~93的数据一并重新计算,因为此时第94天的数据已经和1~93这93天的数据糅合在一个Segment之中了。这对于刷新来说是一种极大的浪费。糟糕的是,即使使用之前所介绍的自动合并的功能,类似的问题也仍然存在,目前为止,还没有一种机制能够有效阻止自动合并试图合并近期N天的Segment,因此使用自动合并仍然有可能将最近N天内的某些Segment与更早的其他Segment合并成一个大的Segment,这个问题将在https://issues.apache.org/jira/browse/KYLIN-1864中获得解决。

目前来说,比较折中的一种方案是不以日为单位创建新的Segment,而是以N天为单位创建新的Segment。举例来说,假设用户每天更新Cube的时候,前面7天的数据都需要更新一下,也就是说,如果今天是01-08,那么用户不仅要添加01-08的新数据,还要同时更新01-01到01-07的数据。在这种情况下,可设置N=7作为最小Segment的长度。在第一天01-01,创建一个新的Segment A,它的时间是从01-01到01-08,我们知道Segment是起始时间闭,结束时间开,因此Segment A的真实长度为7天,也就是01-01到01-07。即使在01-01当天,还没有后面几天的数据,Segment A也能正常地构建,只不过构建出来的Segment其实只有01-01一天的数据而已。从01-02到01-07的每一天,我们都要刷新Segment A,以保证1日到7日的数据保持更新。由于01-01已经是最早的日期,所以不需要对更早的数据进行更新。

到01-08的时候,创建一个新的Segment B,它的时间是从01-08到01-15。此时我们不仅需要构建Segment B,还需要去刷新Segment A。因为01-01到01-07中的数据在01-08当天仍然可能处于更新状态。在接下来的01-09到01-14,每天刷新A、B两个Segment。等到了01-15这天的时候,首先创建一个新的Segment C,它的时间是从01-15到01-22。在01-15当天,Segment A的数据应当已经被视作最终状态,因为Segment A中的最后一天(01-07)已经不再过去N天的范围之内了。因此此时接下来只需要照顾Segment B和Segment C即可。

由此可以看到,在任意一天内,我们只需要同时照顾两个Segment,第一个Segment主要以刷新近期数据为主,第二个Segment则兼顾了加入新数据与刷新近期数据。这个过程中可能存在少量的多余计算,但是每天多余计算的数据量不会超过N天的数据量。这对于Kylin整体的计算量来说是可以接受的。根据业务场景的不同,N可能是7天,也有可能是30天,我们可以适度地把最小的Segment设置成比N稍微大一点的数字,例如N为7的时候,我们可以设置为10天,这样即使ETL有时候没有能够遵守N=7的约定,也仍然能够刷新足够的数据。值得一提的是,在https://issues.apache.org/jira/browse/KYLIN-1864得到解决之前,我们不要重叠使用自动合并和本节中所描述的处理数据陆续更新的策略。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值