OLAP 玩转KYLIN 步七 官方案列实战之创建Cube之设计度量

时间:2022-03-05 07:08:14

紧接上一节,我们继续来看Cube创建的又一关键点,设计度量。


进入度量添加界面,Kylin默认会为我们创建一个Count(1)的度量,避免不必要的麻烦,不要对其做修改或删除。如图:
OLAP 玩转KYLIN 步七 官方案列实战之创建Cube之设计度量
点击上图中的+Measure便可以添加我们自己的度量。
Kylin支持的度量有:SUM、MIN、MAX、COUNT、COUNT DISTINCT、TOP_N、RAW等。选择需要的度量
类型,然后再选择适当的参数(通常为列名)。下面我们来进行添加。

SUM
OLAP 玩转KYLIN 步七 官方案列实战之创建Cube之设计度量
DISTINCT
OLAP 玩转KYLIN 步七 官方案列实战之创建Cube之设计度量
Apache Kylin提供了两种Count Distinct计算方式,一种是近似的,一种是精确的,精确的Count Distinct指标在Build时候
会消耗更多的资源(内存和存储),Build的过程也比较慢。

近似Count Distinct

Apache Kylin使用HyperLogLog算法实现了近似Count Distinct,提供了错误率从9.75%到1.22%几种精度供选择;
算法计算后的Count Distinct指标,理论上,结果最大只有64KB,最低的错误率是1.22%;
这种实现方式用在需要快速计算、节省存储空间,并且能接受错误率的Count Distinct指标计算。

精准Count Distinct

Kylin中实现了基于bitmap的精确Count Distinct计算方式。当数据类型为tiny int(byte)、small int(short)以及int,
会直接将数据值映射到bitmap中;当数据类型为long,string或者其他,则需要将数据值以字符串形式编码成dict(字典),再将字典ID映射到bitmap;
指标计算后的结果,并不是计数后的值,而是包含了序列化值的bitmap.这样,才能确保在任意维度上的Count Distinct结果是正确的。
这种实现方式提供了精确的无错误的Count Distinct结果,但是需要更多的存储资源,如果数据中的不重复值超过百万,结果所占的存储应该会达到几百MB。

全局字典(Global Dictionary)

默认情况下,Kylin在每个Segment中,将数据值编码到一个字典中,同一个数据值,在不同Segment中编码后的值是不同的,因此在跨两个Segment中进行Count Distinct计算时候,结果是不正确的;
在1.5.3版本中,Kylin引进了”Global Dictionary”,用来确保同一个数据值编码后的值始终是相同的,与此同时,字典的容量也进行了扩充,一个字典的最大容量达到了20亿,之前默认的字典最大容量为500万。全局字典可以代替之前的默认字典。
版本1.5.3的UI中,没有提供定义全局字典的地方,需要手动修改Cube的json:

"dictionaries": [
    {
       "column": "SUCPAY_USERID",
           "reuse": "USER_ID",
       "builder": "org.apache.kylin.dict.GlobalDictionaryBuilder"
    }
]

“column”是需要编码(进行Count Distinct计算)的字段,”builder”指定了字典的builder类,目前只能是”org.apache.kylin.dict.GlobalDictionaryBuilder”.
“reuse”是用来优化字典的,当多个字段的值是同一个数据集的时候,指定复用同一个字典即可,不需要再建立字典。
全局字典不能用在维度的编码中,如果一个字段即是维度,又是Count Distinct指标,那么就需要为维度指定其他的编码方式。

性能优化

全局字典是比较大的,在Build时候,”Build Base Cuboid Data”这一步会消耗较长时间。
如果字典大小超过Mapper的内存大小时候,字典需要消耗大量时间在缓存加载和回收上,解决该问题的办法是修改Cube的参数,适当增大Mapper使用的内存:
kylin.job.mr.config.override.mapred.map.child.java.opts=-Xmx8g
kylin.job.mr.config.override.mapreduce.map.memory.mb=8500

总结

选择哪种Count Distinct计算方式呢?
1. 如果能接受1.22%以内的误差,近似计算肯定是最好的方式;
2. 如果业务需要精确去重计数,那么肯定得选择精确Count Distinct;
3. 如果不需要跨Segment(天)的去重,或者字段值是tinyint/smallint/int, 或者字段去重后的值小于500万,那么就是用默认字典;
否则,就需要配置全局字典,同时,如果可以,则是用”reuse”来进行优化。

TOP_N
OLAP 玩转KYLIN 步七 官方案列实战之创建Cube之设计度量

RAW
RAW 度量函数是为了查询明细数据而设计的。
如下数据:

DT SITE_ID SELLER_ID ITEM_COUNT
2016-05-01 0 SELLER-001 100
2016-05-01 0 SELLER-002 200
2016-05-02 1 SELLER-003 300
2016-05-02 1 SELLER-004 400
2016-05-03 2 SELLER-005 500
我们用 DT,SITE_ID 两列作为维度, SUM(ITEM_COUNT) 作为度量。那聚合结果如下:
Rowkey of base cuboid SUM(ITEM_COUNT)
2016-05-01_0 300
2016-05-02_1 700
2016-05-03_2 500
我们拿第一行数据来看, Kylin 从维度列2016-05-01,0 的值组合的HBase Rowkey得到存储在hbase中的聚合结果300, 但我们得不到聚合前的原始明细数据 100 和 200 。

有了 RAW 度量函数,我们用 DT,SITE_ID 作为维度列, RAW(ITEM_COUNT)作为度量。这样,我们就可以对明细数据进行查询了,如:SELECT DT,SITE_ID,ITEM_COUNT FROM FACT_TABLE WHERE SITE_ID = 0
用RAW 来度量的列默认用dict编码。所以,你必须要清楚用来度量列的基数和数据的分布特征。
如果你选择了一个基数很大的列用RAW来进行度量,你可以按下面的办法操作,避免dict构建数据量太大引起的错误:
1.将一个大的segment切分成多个小的segments;
2.在 conf/kylin.properties中设置 kylin.dictionary.max.cardinality 为一个更大的值(默认 5000000).


至此,cube度量的设计已经完成,本案例结果如图:
OLAP 玩转KYLIN 步七 官方案列实战之创建Cube之设计度量
点击Next进入下一步,关于Cube数据刷新的设置。