作者: 康凯森
日期: 2016-10-07
分类: OLAP
本文主要介绍Apache Kylin进行维度优化的常见方法。
因为如果不进行任何维度优化,直接将所有的维度放在一个聚集组里,Kylin就会计算所有的维度组合(cuboid)。
比如,有12个维度,Kylin就会计算2的12次方即4096个cuboid,实际上查询可能用到的cuboid不到1000个,甚至更少。 如果对维度不进行优化,会造成集群计算和存储资源的浪费,也会影响cube的build时间和查询性能,所以我们需要进行cube的维度优化。
当你在保存cube时遇到下面的异常信息时,意味1个聚集组的维度组合数已经大于 4096 ,你就必须进行维度优化了。
当有层次维度时,公式如下:
(hierarchy.size() + 1) * hierarchyDimsList.size() * (1 << jointDimsList.size()) * (1 << normalDims.size())
当没有层次维度时,公式如下:
1 << jointDimsList.size()) * (1 << normalDims.size()
hierarchyDimsList.size(): 层次维度的个数。
hierarchy.size(): 每个层次维度包含的维度个数。
jointDimsList.size(): 联合维度的个数。
normalDims.size(): 正常维度的个数,即不是强制维度,层次维度,联合维度的维度数目。
首先请确认你设置的cube维度都是你查询时会使用到的。
目前Kylin可以使用的维度优化手段有以下几种:
下文会详细介绍以上维度优化手段的基本概念,以及何时使用这些优化手段。
聚集组:用来控制哪些cuboid需要计算。
适用场景:不是只需要计算base cuboid的情况下,都需要聚集组。
注意事项:一个维度可以出现在多个聚集组中,但是build期间只会计算一次。
如果不设置聚集组,默认情况下只会计算 base cuboid。
聚集组不宜太多。
衍生维度:维表中可以由主键推导出值的列可以作为衍⽣维度。
使用场景:以星型模型接入时。例如用户维表可以从userid推导出用户的姓名,年龄,性别。
优化效果:维度表的N个维度组合成的cuboid个数会从2的N次方降为2。
图示:
强制维度:所有cuboid必须包含的维度,不会计算不包含强制维度的cuboid。
适用场景:可以将确定在查询时一定会使用的维度设为强制维度。例如,时间维度。
优化效果:将一个维度设为强制维度,则cuboid个数直接减半。
图示:
层次维度:具有一定层次关系的维度。
使用场景:像年,月,日;国家,省份,城市这类具有层次关系的维度。
优化效果:将N个维度设置为层次维度,则这N个维度组合成的cuboid个数会从2的N次方减少到N+1。
图示:
联合维度:将几个维度视为一个维度。
适用场景: 1 可以将确定在查询时一定会同时使用的几个维度设为一个联合维度。
2 可以将基数很小的几个维度设为一个联合维度。
3 可以将查询时很少使用的几个维度设为一个联合维度。
优化效果:将N个维度设置为联合维度,则这N个维度组合成的cuboid个数会从2的N次方减少到1。
在OLAP分析场景中,经常存在对某个id进行过滤,但查询结果要展示为name的情况,比如user_id和user_name。这类问题通常有三种解决方式:
a. 将ID和Name都设置为维度,查询语句类似
select name, count(*) from table where id = 1 group by id,name
。这种方式的问题是会导致维度增多,导致预计算结果膨胀;b. 将id和name都设置为维度,并且将两者设置为联合。这种方式的好处是保持维度组合数不会增加,但限制了维度的其它优化,比如ID不能再被设置为强制维度或者层次维度;
c. 将ID设置为维度,Name设置为特殊的Measure,类型为Extended Column。这种方式既能保证过滤id且查询name的需求,同时也不影响id维度的进一步优化。
所以此类需求我们推荐使用 Extended Column。
简单的讲,查询频率越高的维度在Rowkey中的顺序需要越靠前。