Apache Kylin权威指南
上QQ阅读APP看书,第一时间看更新

bleed

第2章 快速入门

第1章介绍了Kylin的概况,以及与其他SQL on Hadoop技术的比较,相信读者对Kylin已经有了一个整体的认识。本章将详细介绍Kylin的一些核心概念,然后带领读者逐步定义数据模型,创建Cube,并通过SQL来查询Cube,以帮助读者对Kylin有更为直观的了解。

2.1 核心概念

在开始使用Kylin之前,我们有必要先了解一下Kylin里的各种概念和术语,为后续章节的学习奠定基础。

2.1.1 数据仓库、OLAP与BI

数据仓库(Data Warehouse)是一种信息系统的资料储存理论,此理论强调的是利用某些特殊的资料储存方式,让所包含的资料特别有利于分析和处理,从而产生有价值的资讯,并可依此做出决策。

利用数据仓库的方式存放的资料,具有一旦存入,便不会随时间发生变动的特性,此外,存入的资料必定包含时间属性,通常一个数据仓库中会含有大量的历史性资料,并且它可利用特定的分析方式,从其中发掘出特定的资讯。

OLAP(Online Analytical Process),联机分析处理,以多维度的方式分析数据,而且能够弹性地提供上卷(Roll-up)、下钻(Drill-down)和透视分析(Pivot)等操作,它是呈现集成性决策信息的方法,多用于决策支持系统、商务智能或数据仓库。其主要的功能在于方便大规模数据分析及统计计算,可对决策提供参考和支持。与之相区别的是联机交易处理(OLTP),联机交易处理,更侧重于基本的、日常的事务处理,包括数据的增删改查。

❑ OLAP需要以大量历史数据为基础,再配合上时间点的差异,对多维度及汇整型的信息进行复杂的分析。

❑ OLAP需要用户有主观的信息需求定义,因此系统效率较佳。

OLAP的概念,在实际应用中存在广义和狭义两种不同的理解方式。广义上的理解与字面上的意思相同,泛指一切不会对数据进行更新的分析处理。但更多的情况下OLAP被理解为其狭义上的含义,即与多维分析相关,基于立方体(Cube)计算而进行的分析。

BI(Business Intelligence),即商务智能,指用现代数据仓库技术、在线分析技术、数据挖掘和数据展现技术进行数据分析以实现商业价值。

今天,许多企业已经建立了自己的数据仓库,用于存放和管理不断增长的数据;这些数据中蕴含着丰富的价值,但只有通过使用一系列的分析工具,进行大量的筛选、计算和展示,数据中蕴含的规律和潜在的信息才能被人们所发现;分析人员可结合这些信息展开商业决策和市场活动,从而为用户提供更好的服务,或为企业产生更大的价值。

2.1.2 维度和度量

维度和度量是数据分析中的两个基本概念。

维度是指审视数据的角度,它通常是数据记录的一个属性,例如时间、地点等。度量是基于数据所计算出来的考量值;它通常是一个数值,如总销售额、不同的用户数等。分析人员往往要结合若干个维度来审查度量值,以便在其中找到变化规律。在一个SQL查询中,Group By的属性通常就是维度,而所计算的值则是度量。如下面的示例:

        select  part_dt,  lstg_site_id,  sum(price)  as  total_selled,  count(distinct seller_id) as sellers from kylin_sales group by part_dt, lstg_site_id

在上面的这个查询中,part_dt和lstg_site_id是维度,sum(price)和count(distinct seller_id)是度量。

2.1.3 事实表和维度表

事实表(Fact Table)是指存储有事实记录的表,如系统日志、销售记录等;事实表的记录在不断地动态增长,所以它的体积通常远大于其他表。

维度表(Dimension Table)或维表,有时也称查找表(Lookup Table),是与事实表相对应的一种表;它保存了维度的属性值,可以跟事实表做关联;相当于将事实表上经常重复出现的属性抽取、规范出来用一张表进行管理。常见的维度表有:日期表(存储与日期对应的周、月、季度等的属性)、地点表(包含国家、省/州、城市等属性)等。使用维度表有诸多好处,具体如下。

❑ 缩小了事实表的大小。

❑ 便于维度的管理和维护,增加、删除和修改维度的属性,不必对事实表的大量记录进行改动。

❑ 维度表可以为多个事实表重用,以减少重复工作。

2.1.4 Cube、Cuboid和Cube Segment

Cube(或Data Cube),即数据立方体,是一种常用于数据分析与索引的技术;它可以对原始数据建立多维度索引。通过Cube对数据进行分析,可以大大加快数据的查询效率。

Cuboid在Kylin中特指在某一种维度组合下所计算的数据。

Cube Segment是指针对源数据中的某一个片段,计算出来的Cube数据。通常数据仓库中的数据数量会随着时间的增长而增长,而Cube Segment也是按时间顺序来构建的。

2.2 在Hive中准备数据

2.1节介绍了Kylin中的常见概念。本节将介绍准备Hive数据的一些注意事项。需要被分析的数据必须先保存为Hive表的形式,然后Kylin才能从Hive中导入数据,创建Cube。

Apache Hive是一个基于Hadoop的数据仓库工具,最初由Facebook开发并贡献到Apache软件基金会。Hive可以将结构化的数据文件映射为数据库表,并可以将SQL语句转换为MapReduce或Tez任务进行运行,从而让用户以类SQL(HiveQL,也称HQL)的方式管理和查询Hadoop上的海量数据。

此外,Hive还提供了多种方式(如命令行、API和Web服务等)可供第三方方便地获取和使用元数据并进行查询。今天,Hive已经成为Hadoop数据仓库的首选,是Hadoop上不可或缺的一个重要组件,很多项目都已兼容或集成了Hive。基于此情况,Kylin选择Hive作为原始数据的主要来源。

在Hive中准备待分析的数据是使用Kylin的前提;将数据导入到Hive表中的方法有很多,用户管理数据的技术和工具也各式各样,因此具体步骤不在本书的讨论范围之内。如有需要可以参考Hive的使用文档。这里将着重阐述需要注意的几个事项。

2.2.1 星形模型

数据挖掘有几种常见的多维数据模型,如星形模型(Star Schema)、雪花模型(Snowf lake Schema)、事实星座模型(Fact Constellation)等。

星形模型中有一张事实表,以及零个或多个维度表;事实表与维度表通过主键外键相关联,维度表之间没有关联,就像很多星星围绕在一个恒星周围,故取名为星形模型。

如果将星形模型中某些维度的表再做规范,抽取成更细的维度表,然后让维度表之间也进行关联,那么这种模型称为雪花模型。

星座模型是更复杂的模型,其中包含了多个事实表,而维度表是公用的,可以共享。

不过,Kylin只支持星形模型的数据集,这是基于以下考虑。

❑ 星形模型是最简单,也是最常用的模型。

❑ 由于星形模型只有一张大表,因此它相比于其他模型更适合于大数据处理。

❑ 其他模型可以通过一定的转换,变为星形模型。

2.2.2 维度表的设计

除了数据模型以外,Kylin还对维度表有一定的要求,具体要求如下。

1)要具有数据一致性,主键值必须是唯一的;Kylin会进行检查,如果有两行的主键值相同则会报错。

2)维度表越小越好,因为Kylin会将维度表加载到内存中供查询;过大的表不适合作为维度表,默认的阈值是300MB。

3)改变频率低,Kylin会在每次构建中试图重用维度表的快照,如果维度表经常改变的话,重用就会失效,这就会导致要经常对维度表创建快照。

4)维度表最好不要是Hive视图(View),虽然在Kylin 1.5.3中加入了对维度表是视图这种情况的支持,但每次都需要将视图进行物化,从而导致额外的时间开销。

2.2.3 Hive表分区

Hive表支持多分区(Partition)。简单地说,一个分区就是一个文件目录,存储了特定的数据文件。当有新的数据生成的时候,可以将数据加载到指定的分区,读取数据的时候也可以指定分区。对于SQL查询,如果查询中指定了分区列的属性条件,则Hive会智能地选择特定分区(也就是目录),从而避免全量数据的扫描,减少读写操作对集群的压力。

下面列举的一组SQL演示了如何使用分区:

        Hive> create table invites (id int, name string) partitioned by (ds string) row format delimited fields terminated by 't' stored as textfile;
        Hive>  load  data  local  inpath  '/user/hadoop/data.txt'  overwrite  into  table invites partition (ds='2016-08-16');
        Hive> select * from invites where ds ='2016-08-16';

Kylin支持增量的Cube构建,通常是按时间属性来增量地从Hive表中抽取数据。如果Hive表正好是按此时间属性做分区的话,那么就可以利用到Hive分区的好处,每次在Hive构建的时候都可以直接跳过不相干日期的数据,节省Cube构建的时间。这样的列在Kylin里也称为分割时间列(Partition Time Column),通常它应该也是Hive表的分区列。

2.2.4 了解维度的基数

维度的基数(Cardinality)指的是该维度在数据集中出现的不同值的个数;例如“国家”是一个维度,如果有200个不同的值,那么此维度的基数就是200。通常一个维度的基数会从几十到几万个不等,个别维度如“用户ID”的基数会超过百万甚至千万。基数超过一百万的维度通常被称为超高基数维度(Ultra High Cardinality, UHC),需要引起设计者的注意。

Cube中所有维度的基数都可以体现出Cube的复杂度,如果一个Cube中有好几个超高基数维度,那么这个Cube膨胀的概率就会很高。在创建Cube前需要对所有维度的基数做一个了解,这样就可以帮助设计合理的Cube。计算基数有多种途径,最简单的方法就是让Hive执行一个count distinct的SQL查询;Kylin也提供了计算基数的方法,在2.3.1节中会进行介绍。

2.2.5 Sample Data

如果需要一些简单数据来快速体验Apache Kylin,也可以使用Apache Kylin自带的Sample Data。运行“${KYLIN_HOME}/bin/sample.sh”来导入Sample Data,然后就能按照下面的流程继续创建模型和Cube。

具体请执行下面命令,将Sample Data导入Hive数据库。

        cd ${KYLIN_HOME}
        bin/sample.sh

Sample Data测试的样例数据集总共仅1MB左右,共计3张表,其中事实表有10000条数据。因为数据规模较小,有利于在虚拟机中进行快速实践和操作。数据集是一个规范的星形模型结构,它总共包含了3个数据表:

❑ KYLIN_SALES是事实表,保存了销售订单的明细信息。各列分别保存着卖家、商品分类、订单金额、商品数量等信息,每一行对应着一笔交易订单。

❑ KYLIN_CATEGORY_GROUPINGS是维表,保存了商品分类的详细介绍,例如商品分类名称等。

❑ KYLIN_CAL_DT也是维表,保存了时间的扩展信息。如单个日期所在的年始、月始、周始、年份、月份等。

这3张表一起构成了整个星形模型。

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-1 输入Hive表名

导入成功后,表的结构信息会以树状的形式显示在页面的左侧,可以单击展开或收缩,如图2-2所示。

图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-6 选择维度列

选择度量列时,度量只能来自事实表,如图2-7所示。

图2-7 选择度量列

最后一步,是为模型补充分割时间列信息和过滤条件。如果此模型中的事实表记录是按时间增长的,那么可以指定一个日期/时间列作为模型的分割时间列,从而可以让Cube按此列做增量构建,关于增量构建的具体内容请参见第3章。

过滤(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-10 添加普通维度

如果是衍生维度的话,则必须是来自于某个维度表,一次可以选择多个列(如图2-11所示);由于这些列值都可以从该维度表的主键值中衍生出来,所以实际上只有主键列会被Cube加入计算。而在Kylin的具体实现中,往往采用事实表上的外键替代主键进行计算和存储。但是在逻辑上可以认为衍生列来自于维度表的主键。

图2-11 添加衍生维度

使用第二种方法的时候,Kylin会用一个树状结构呈现出所有的列,用户只需要勾选所需要的列即可,Kylin会自动补齐其他信息,从而方便用户的操作(如图2-12所示)。请注意,在这里Kylin会把维度表上的列都创建成衍生维度,这也许不是最合适的,在这种情况下,请使用第一种方法。

图2-12 批量添加维度

第三页,创建度量。Kylin默认会创建一个Count(1)的度量。可以单击“+Measure”按钮来添加新的度量。Kylin支持的度量有:SUM、MIN、MAX、COUNT、COUNT DISTINCT、TOP_N、RAW等。请选择需要的度量类型,然后再选择适当的参数(通常为列名)。图2-13是一个SUM(price)的示例。

图2-13 添加度量

重复上面的步骤,创建所需要的度量。Kylin可以支持在一个Cube中添加多达上百个的度量;添加完所有度量之后,单击“Next”,如图2-14所示。

图2-14 度量列表

第四页,是关于Cube数据刷新的设置。在这里可以设置自动合并的阈值、数据保留的最短时间,以及第一个Segment的起点时间(如果Cube有分割时间列的话),详细内容请参考第3章。

图2-15 刷新设置

第五页,高级设置。在此页面上可以设置聚合组和Rowkey(如图2-16所示)。

图2-16 高级设置

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中进行比较查询的时候,依然使用编码后的值,而无需解码。

字典非常适合于非固定长度的string类型值的维度,而且用户无需指定编码后的长度;但是由于使用字典需要维护一张映射表,因此如果此维度的基数很高,那么字典的大小就非常可观,从而不适合于加载到内存中,在这种情况下就要选择其他的编码方式了。Kylin中字典编码允许的基数上限默认是500万(由参数“kylin.dictionary.max.cardinality”配置)。

整数(int)编码适合于对int或bigint类型的值进行编码,它无需额外存储,同时还可以支持很大的基数。用户需要根据值域选择编码的长度。例如有一个“手机号码”的维度,它是一个11位的数字,如13800138000,我们知道它大于231,但是小于239-1,那么使用int(5)即可满足要求,每个值占用5字节,比按字符存储(11字节)要少占用一半以上的空间。

当上面几种编码方式都不适合的时候,就需要使用固定长度的编码了;此编码方式其实只是将原始值截断或补齐成相同长度的一组字节,没有额外的转换,所以空间效率较差,通常只是作为一种权宜手段。

各维度在Rowkeys中的顺序,对于查询的性能会产生较明显的影响。在这里用户可以根据查询的模式和习惯,通过拖曳的方式调整各个维度在Rowkeys上的顺序(如图2-17所示)。通常的原则是,将过滤频率较高的列放置在过滤频率较低的列之前,将基数高的列放置在基数低的列之前。这样做的好处是,充分利用过滤条件来缩小在HBase中扫描的范围,从而提高查询的效率。

图2-17 Rowkey设置

第五页,为Cube配置参数。和其他Hadoop工具一样,Kylin使用了很多配置参数以提高灵活性,用户可以根据具体的环境、场景等配置不同的参数进行调优。Kylin全局的参数值可在conf/kylin.properties文件中进行配置;如果Cube需要覆盖全局设置的话,则需要在此页面中指定。单击“+Property”按钮,然后输入参数名和参数值,如图2-18所示,指定“kylin.hbase.region.cut=1”,这样此Cube在存储的时候,Kylin将会为每个HTable Region分配1GB来创建一个HTable Region。

图2-18 覆盖默认参数

然后单击Next跳转到最后一个确认页面,如有修改,则单击“Prev”按钮返回以修改,最后再单击“Save”按钮进行保存,一个Cube就创建完成了。创建好的Cube会显示在“Cubes”列表中,如要对Cube的定义进行修改,只需单击“Edit”按钮就可以进行修改。也可以展开此Cube行以查看更多的信息,如JSON格式的元数据、访问权限、通知列表等。

2.4 构建Cube

注意

本节将快速介绍构建Cube相关的操作说明和设置,因受到篇幅的限制,许多具体内容无法深入展开,读者可以从后续的第3章和第4章中获得更详细的介绍。

新创建的Cube只有定义,而没有计算的数据,它的状态是“DISABLED”,是不会被查询引擎挑中的。要想让Cube有数据,还需要对它进行构建。Cube的构建方式通常有两种:全量构建和增量构建;两者的构建步骤是完全一样的,区别只在于构建时读取的数据源是全集还是子集。

Cube的构建包含如下步骤,由任务引擎来调度执行。

1)创建临时的Hive平表(从Hive读取数据)。

2)计算各维度的不同值,并收集各Cuboid的统计数据。

3)创建并保存字典。

4)保存Cuboid统计信息。

5)创建HTable。

6)计算Cube(一轮或若干轮MapReduce)。

7)将Cube的计算结果转成HFile。

8)加载HFile到HBase。

9)更新Cube元数据。

10)垃圾回收。

以上步骤中,前5步是为计算Cube而做的准备工作,例如遍历维度值来创建字典,对数据做统计和估算以创建HTable等;第6)步是真正的Cube计算,取决于所使用的Cube算法,它可能是一轮MapReduce任务,也可能是N(在没有优化的情况下,N可以被视作是维度数)轮迭代的MapReduce。由于Cube运算的中间结果是以SequenceFile的格式存储在HDFS上的,所以为了导入到HBase中,还需要第7)步将这些结果转换成HFile(HBase文件存储格式)。第8)步通过使用HBase BulkLoad工具,将HFile导入进HBase集群,这一步完成之后,HTable就可以查询到数据了。第9)步更新Cube的数据,将此次构建的Segment的状态从“NEW”更新为“READY”,表示已经可供查询了。最后一步,清理构建过程中生成的临时文件等垃圾,释放集群资源。

Monitor页面会显示当前项目下近期的构建任务。图2-19显示了一个正在运行的Cube构建的任务,当前进度为46%多。

图2-19 任务列表

单击任务右边的“ ”按钮,展开可以得到任务每一步的详细信息,如图2-20所示。

图2-20 任务步骤列表

如果任务中的某一步是执行Hadoop任务的话,那么会显示Hadoop任务的链接,单击即可跳转到对应的Hadoop任务监测页面,如图2-21所示。

图2-21 MapReduce任务监测页面

如果任务执行中的某一步出现报错,那么任务引擎会将任务状态置为“ERROR”并停止后续的执行,等待用户排错。在错误排除之后,用户可以单击“Resume”从上次失败的地方恢复执行。或者如果需要修改Cube或重新开始构建,那么用户需要单击“Discard”来丢弃此次构建。

接下来将介绍几种不同的构建方式。

2.4.1 全量构建和增量构建

1.全量构建

对数据模型中没有指定分割时间列信息的Cube, Kylin会采用全量构建,即每次从Hive中读取全部的数据来开始构建。通常它适用于以下两种情形。

❑ 事实表的数据不是按时间增长的。

❑ 事实表的数据比较小或更新频率很低,全量构建不会造成太大的开销。

2.增量构建

增量构建的时候,Kylin每次都会从Hive中读取一个时间范围内的数据,然后进行计算,并以一个Segment的形式进行保存。下次再构建的时候,会自动以上次结束的时间为起点时间,再选择新的终止时间进行构建。经过多次构建,Cube中将会有多个Segment依次按时间顺序进行排列,如Seg-1, Seg-2, …, Seg-N。查询的时候,Kylin会查询一个或多个Segment然后再做聚合计算,以便返回正确的结果给请求者。

使用增量构建的好处是,每次只需要对新增数据进行计算,从而避免了对历史数据进行重复计算。对于数据量很大的Cube,使用增量构建是非常有必要的。

图2-22是构建一个Segment的Cube时的输入框,需要用户选择时间范围。

图2-22 提交增量构建

在从Hive读取源数据的时候,Kylin会带上此时间条件,如图2-23所示。

图2-23 增量构建的SQL

注意

增量构建抽取数据的范围,采用了前包后闭的原则,即包含了开始时间,但不包含结束时间,从而保证上一个Segment的结束时间与下一个Segment的起始时间相同,但数据不会重复。

下一次构建的时候,起始时间必须是上一次的结束时间。如果使用Kylin的Web GUI触发,那么起始时间会被自动填写,用户只需要选择结束时间。如果使用Rest API触发,用户则需要确保时间范围不会与已有的Segment有重合。

2.4.2 历史数据刷新

Cube构建完成以后,如果某些历史数据发生了改动,那么需要针对相应的Segment进行重新计算,这种构建称为刷新。刷新通常只针对增量构建的Cube而言,因为全量构建的Cube只要重新全部构建就可以得到更新;而增量更新的Cube因为有多个Segment,因此需要先选择要刷新的Segment,然后再进行刷新。

图2-24是提交刷新的请求页面,用户需要在下拉列表中选择一个时间区间。

图2-24 刷新已有的Segment

提交以后,生成的构建任务与最初的构建任务完全一样。

在刷新的同时,Cube仍然可以被查询,只不过返回的是陈旧数据。当Segment刷新完毕时,新的Segment会立即生效,查询开始返回最新的数据。老Segment则成为垃圾,等待回收。

2.4.3 合并

随着时间的迁移,Cube中可能会存在较多数量的Segment,使得查询性能下降,并且会给HBase集群管理带来压力。对此,需要适时地将一些Segment进行合并,将若干个小Segment合并成较大的Segment。

合并的好处具体如下。

❑ 合并相同的Key,从而减少Cube的存储空间。

❑ 由于Segment减少了,因此可以减少查询时的二次聚合,提高了查询性能。

❑ HTable的数量得以减少,更便于集群的管理。

下面来看看合并的操作步骤,图2-25中的Cube有两个Segment。

图2-25 Cube Segment列表

现在触发一个合并,单击Actions →Merge;选择要合并的起始Segment和结束Segment,生成一个合并的任务,如图2-26所示。

图2-26 提交合并任务

合并的时候,Kylin将直接以当初各个Segment构建时生成的Cuboid文件作为输入内容,而不需要从Hive加载原始数据。后续的步骤跟构建时基本一致。直到新的HTable加载完成后,Kylin才会卸载旧的HTable,从而确保在整个合并过程中,Cube都是可以查询的。

合并完成之后,此Cube的Segment减少为1个,如图2-27所示。

图2-27 合并后的Segment

2.5 查询Cube

注意

本节将简要介绍如何查询Cube。更多内容请参考后续的章节(如第5章)。

Cube构建好以后,状态变为“READY”,就可以进行查询了。Kylin的查询语言是标准SQL的SELECT语句,这是为了获得与大多数BI系统和工具无缝集成的可能性。通常的一个查询语句类似于如下的SQL:

        SELECT DIM1, DIM2, …, MEASURE1, MEASURE2… FROM FACT_TABLE
            INNER JOIN LOOKUP_1 ON FACT_TABLE.FK1 = LOOKUP_1.PK
            INNER JOIN LOOKUP_2 ON FACT_TABLE.FK2 = LOOKUP_2.PK
        WHERE FACT_TABLE.DIMN =‘'AND …
            GROUP BY DIM1, DIM2…

需要了解的是,只有当查询的模式跟Cube定义相匹配的时候,Kylin才能够使用Cube的数据来完成查询。Group By的列和Where条件里的列,必须是在Dimension中定义的列,而SQL中的度量,应该跟Cube中定义的度量相一致。

在一个项目下,如果有多个基于同一模型的Cube,而且它们都满足查询对表、维度和度量的要求;那么,Kylin会挑选一个“最优的”Cube来进行查询;这是一种基于成本(cost)的选择,Cube的成本计算中包括多方面的因素,例如Cube的维度数、度量、数据模型的复杂度等。查询引擎将为每个Cube为完成此SQL估算一个成本值,然后选择成本最小的Cube来完成此查询。

如果查询是在Kylin的Web GUI上进行的,那么查询结果会以表的形式展现出来,如图2-28所示。所执行的Cube名称也会一同显示。用户可以单击“Visualization”按钮生成简单的可视化图形,或单击“Export”按钮将结果集下载到本地。

图2-28 查询结果展示

2.6 SQL参考

Apache Kylin支持标准SQL作为查询语言,但是SQL有很多变体,Kylin支持的只是SQL所有变体中的一个子集,并不是支持所有现存的SQL语句和语法。用户在使用Kylin之前,需要对Kylin所支持的SQL有一个了解,以避免走弯路。

首先,Kylin作为OLAP引擎,只支持查询,而不支持其他操作,如插入、更新等,即所有的SQL都必须是SELECT语句,否则Kylin会报错。

第二,查询Kylin中SQL语句的表名、列名、度量、连接关系时,需要至少跟一个Cube的模型相匹配;在设计Cube的时候,需要充分考虑查询的需求,避免遗漏表、列等信息。

第三,Kylin使用Apache Calcite做SQL语法分析。Apache Calcite是一个开源的SQL引擎,它提供了标准SQL解析、多种查询优化和连接各种数据源的能力;Calcite项目在Hadoop中越来越引人注意,并且已被众多项目集成为SQL解析器。

一条SQL语句首先需要被Calcite解析,然后才可以被Kylin执行。下面是Calcite中的SELECT语句的语法(引自https://calcite.apache.org/docs/reference.html):

        SELECT [ STREAM ] [ ALL | DISTINCT ]
                    { * | projectItem [, projectItem ]* }
                 FROM tableExpression
                 [ WHERE booleanExpression ]
                 [ GROUP BY { groupItem [, groupItem ]* } ]
                 [ HAVING booleanExpression ]
                 [ WINDOW windowName AS windowSpec [, windowName AS windowSpec ]* ]
        projectItem:
                 expression [ [ AS ] columnAlias ]
            |    tableAlias . *
        tableExpression:
                 tableReference [, tableReference ]*
            |    tableExpression [ NATURAL ] [ LEFT | RIGHT | FULL ] JOIN tableExpression
    [ joinCondition ]
        joinCondition:
                 ON booleanExpression
            |    USING '(' column [, column ]* ')'

第四,不是所有的Calcite能够解析的SELECT语句都可以被Kylin执行;还有一些SQL功能,现阶段Kylin(截止v1.5.3)还不支持,未来会考虑加以实现,目前已知的有如下三项SQL功能。

❑ Window函数:https://issues.apache.org/jira/browse/KYLIN-1732

❑ Union:https://issues.apache.org/jira/browse/KYLIN-1206

❑ Between AND: https://issues.apache.org/jira/browse/KYLIN-1770

上述三个功能已经在Apache Kylin主分支上得以实现,但目前(2016年8月)还未包含在最新的发行版中。如无意外,应该会在下一个发行版中发布。

2.7 小结

本章介绍了使用Apache Kylin必备的基本概念,如星形数据模型、事实表、维表、维度、度量等,并在这些基础上快速创建了基于Sample Data的模型,构建Cube,最后执行SQL查询。带领读者体验了Apache Kylin的主要使用过程。后续的章节将继续展开和探讨这个过程中的一些关键技术,比如增量构建、可视化和Cube优化等。