2.3 设计Cube
如果数据已经在Hive中准备好了,并且已经满足了2.2节中介绍的条件,那么就可以开始设计和创建Cube了。本节将按通常的步骤介绍Cube是如何进行创建的。
2.3.1 导入Hive表定义
登录Kylin的Web界面,创建新的或选择一个已有的项目之后,需要做的就是将Hive表的定义导入到Kylin中。
单击Web界面的Model→Data source下的“Load Hive Table”图标,然后输入表的名称(可以一次导入多张表,以逗号分隔表名,如图2-1所示),单击按钮“Sync”,Kylin就会使用Hive的API从Hive中获取表的属性信息。
导入成功后,表的结构信息会以树状的形式显示在页面的左侧,可以单击展开或收缩,如图2-2所示。
图2-1 输入Hive表名 图2-2 完成导入的Hive表
同时,Kylin会在后台触发一个MapReduce任务,计算此表每个列的基数。通常稍过几分钟之后再刷新页面,就会看到显示出来的基数信息,如图2-3所示。
图2-3 计算后各列的基数
需要注意的是,这里Kylin对基数的计算方法采用的是HyperLogLog的近似算法,与精确值略有误差,但作为参考值已经足够了。
2.3.2 创建数据模型
有了表信息之后,就可以开始创建数据模型(Data Model)了。数据模型是Cube的基础,它主要用于描述一个星形模型。有了数据模型以后,定义Cube的时候就可以直接从此模型定义的表和列中进行选择了,省去重复指定连接(join)条件的步骤。基于一个数据模型还可以创建多个Cube,以方便减少用户的重复性工作。
在Kylin界面的“Models”页面中,单击“New”→“New Model”,开始创建数据模型。给模型输入名称之后,选择一个事实表(必需的),然后添加维度表(可选),如图2-4所示。
图2-4 选择事实表
添加维度表的时候,需要选择连接的类型:是Inner还是Left,然后选择连接的主键和外键,这里也支持多主键,如图2-5所示。
图2-5 选择维度表
接下来选择会用作维度和度量的列。这里只是选择一个范围,不代表这些列将来一定要用作Cube的维度或度量,你可以把所有可能会用到的列都选进来,后续创建Cube的时候,将只能从这些列中进行选择。
选择维度列时,维度可以来自事实表或维度表,如图2-6所示。
选择度量列时,度量只能来自事实表,如图2-7所示。
最后一步,是为模型补充分割时间列信息和过滤条件。如果此模型中的事实表记录是按时间增长的,那么可以指定一个日期/时间列作为模型的分割时间列,从而可以让Cube按此列做增量构建,关于增量构建的具体内容请参见第3章。
图2-6 选择维度列
图2-7 选择度量列
过滤(Filter)条件是指,如果想把一些记录忽略掉,那么这里可以设置一个过滤条件。Kylin在向Hive请求源数据的时候,会带上此过滤条件。在图2-8所示的示例中,会直接排除掉金额小于等于0的记录。
图2-8 选择分区列和设定过滤器
最后,单击“Save”保存此数据模型,随后它将出现在“Models”的列表中。
2.3.3 创建Cube
本节将快速介绍创建Cube时的各种配置选项,但是由于篇幅的限制,这里将不会对Cube的配置和Cube的优化进行深入的展开介绍。读者可以在后续的章节(如第6章“Cube优化”)中找到关于Cube的更详细的介绍。接下来开始Cube的创建;单击“New”,选择“New Cube”,会开启一个包含若干步骤的向导。
第一页,选择要使用的数据模型,并为此Cube输入一个唯一的名称(必需的)和描述(可选的)(如图2-9所示);这里还可以输入一个邮件通知列表,用于在构建完成或出错时收到通知。如果不想接收处于某些状态的通知,那么可以从“Notif?ication Events”中将其去掉。
图2-9 Cube基本信息
第二页,选择Cube的维度。可以通过以下两个按钮来添加维度。
“Add Dimension”:逐个添加维度,可以是普通维度也可以是衍生(Derived)维度。
“Auto Generator”:批量选择并添加,让Kylin自动完成其他信息。
使用第一种方法的时候,需要为每个维度起个名字,然后选择表和列(如图2-10所示)。
如果是衍生维度的话,则必须是来自于某个维度表,一次可以选择多个列(如图2-11所示);由于这些列值都可以从该维度表的主键值中衍生出来,所以实际上只有主键列会被Cube加入计算。而在Kylin的具体实现中,往往采用事实表上的外键替代主键进行计算和存储。但是在逻辑上可以认为衍生列来自于维度表的主键。
使用第二种方法的时候,Kylin会用一个树状结构呈现出所有的列,用户只需要勾选所需要的列即可,Kylin会自动补齐其他信息,从而方便用户的操作(如图2-12所示)。请注意,在这里Kylin会把维度表上的列都创建成衍生维度,这也许不是最合适的,在这种情况下,请使用第一种方法。
图2-11 添加衍生维度
第三页,创建度量。Kylin默认会创建一个Count(1)的度量。可以单击“+Measure”按钮来添加新的度量。Kylin支持的度量有:SUM、MIN、MAX、COUNT、COUNT DISTINCT、TOP_N、RAW等。请选择需要的度量类型,然后再选择适当的参数(通常为列名)。图2-13是一个SUM(price)的示例。
图2-12 批量添加维度 图2-13 添加度量
重复上面的步骤,创建所需要的度量。Kylin可以支持在一个Cube中添加多达上百个的度量;添加完所有度量之后,单击“Next”,如图2-14所示。
图2-14 度量列表
第四页,是关于Cube数据刷新的设置。在这里可以设置自动合并的阈值、数据保留的最短时间,以及第一个Segment的起点时间(如果Cube有分割时间列的话),详细内容请参考第3章。
第五页,高级设置。在此页面上可以设置聚合组和Rowkey(如图2-16所示)。
图2-15 刷新设置
Kylin默认会把所有维度都放在同一个聚合组中;如果维度数较多(例如>10),那么建议用户根据查询的习惯和模式,单击“New Aggregation Group+”,将维度分为多个聚合组。通过使用多个聚合组,可以大大降低Cube中的Cuboid数量。下面来举例说明,如果一个Cube有(M+N)个维度,那么默认它会有2m+n个Cuboid;如果把这些维度分为两个不相交的聚合组,那么Cuboid的数量将被减少为2m+2n。
在单个聚合组中,可以对维度设置高级属性,如Mandatory、Hierarchy、Joint等。这几种属性都是为优化Cube的计算而设计的,了解这些属性的含义对日后更好地使用Cube至关重要。
Mandatory维度指的是那些总是会出现在Where条件或Group By语句里的维度;通过将某个维度指定为Mandatory,Kylin就可以不用预计算那些不包含此维度的Cuboid,从而减少计算量。
Hierarchy是一组有层级关系的维度,例如“国家”“省”“市”,这里的“国家”是高级别的维度,“省”“市”依次是低级别的维度。用户会按高级别维度进行查询,也会按低级别维度进行查询,但在查询低级别维度时,往往都会带上高级别维度的条件,而不会孤立地审视低级别维度的数据。例如,用户会单击“国家”作为维度来查询汇总数据,也可能单击“国家”+“省”,或者“国家”+“省”+“市”来查询,但是不会跨越国家直接Group By “省”或“市”。通过指定Hierarchy,Kylin可以省略不满足此模式的Cuboid。
Joint是将多个维度组合成一个维度,其通常适用于如下两种情形。
总是会在一起查询的维度。
基数很低的维度。
Kylin以Key-Value的方式将Cube存储到HBase中。HBase的key,也就是Rowkey,是由各维度的值拼接而成的;为了更高效地存储这些值,Kylin会对它们进行编码和压缩;每个维度均可以选择合适的编码(Encoding)方式,默认采用的是字典(Dictionary)编码技术;除了字典以外,还有整数(Int)和固定长度(Fixed Length)的编码。
字典编码是将此维度下的所有值构建成一个从string到int的映射表;Kylin会将字典序列化保存,在Cube中存储int值,从而大大减小存储的大小。另外,字典是保持顺序的,即如果字符串A比字符串B大的话,那么A编码后的int值也会比B编码后的值大;这样可以使得在HBase中进行比较查询的时候,依然使用编码后的值,而无需解码。
图2-16 高级设置
字典非常适合于非固定长度的string类型值的维度,而且用户无需指定编码后的长度;但是由于使用字典需要维护一张映射表,因此如果此维度的基数很高,那么字典的大小就非常可观,从而不适合于加载到内存中,在这种情况下就要选择其他的编码方式了。Kylin中字典编码允许的基数上限默认是500万(由参数“kylin.dictionary.max.cardinality”配置)。
整数(int)编码适合于对int或bigint类型的值进行编码,它无需额外存储,同时还可以支持很大的基数。用户需要根据值域选择编码的长度。例如有一个“手机号码”的维度,它是一个11位的数字,如13800138000,我们知道它大于231,但是小于239-1,那么使用int(5)即可满足要求,每个值占用5字节,比按字符存储(11字节)要少占用一半以上的空间。
当上面几种编码方式都不适合的时候,就需要使用固定长度的编码了;此编码方式其实只是将原始值截断或补齐成相同长度的一组字节,没有额外的转换,所以空间效率较差,通常只是作为一种权宜手段。
各维度在Rowkeys中的顺序,对于查询的性能会产生较明显的影响。在这里用户可以根据查询的模式和习惯,通过拖曳的方式调整各个维度在Rowkeys上的顺序(如图2-17所示)。通常的原则是,将过滤频率较高的列放置在过滤频率较低的列之前,将基数高的列放置在基数低的列之前。这样做的好处是,充分利用过滤条件来缩小在HBase中扫描的范围,从而提高查询的效率。
第五页,为Cube配置参数。和其他Hadoop工具一样,Kylin使用了很多配置参数以提高灵活性,用户可以根据具体的环境、场景等配置不同的参数进行调优。Kylin全局的参数值可在conf/kylin.properties文件中进行配置;如果Cube需要覆盖全局设置的话,则需要在此页面中指定。单击“+Property”按钮,然后输入参数名和参数值,如图2-18所示,指定“kylin.hbase.region.cut=1”,这样此Cube在存储的时候,Kylin将会为每个HTable Region分配1GB来创建一个HTable Region。
图2-17 Rowkey设置
图2-18 覆盖默认参数
然后单击Next跳转到最后一个确认页面,如有修改,则单击“Prev”按钮返回以修改,最后再单击“Save”按钮进行保存,一个Cube就创建完成了。创建好的Cube会显示在“Cubes”列表中,如要对Cube的定义进行修改,只需单击“Edit”按钮就可以进行修改。也可以展开此Cube行以查看更多的信息,如JSON格式的元数据、访问权限、通知列表等。