1 Kylin 概述
1.1 Kylin定义
Apache Kylin 是一个开源的分布式分析引擎,提供 Hadoop/Spark 之上的 SQL 查询接口及多个维度分析(MOLAP)能力以支持超大规模数据,它能在亚秒内查询巨大的 Hive 表。
1.2 术语解释
Data Warehouse(数据仓库):数据仓库是一个各种数据(包括历史数据和当前数据)的中心存储系统,是BI( business intelligence ,商业智能)的核心部件
Business Intelligence(商业智能):商业智能通常被理解为将企业中现有的数据转化为知识,帮助企业做出明智的业务经营决策的工具
OLAP(online analytical processing):OLAP(online analytical processing)是一种软件技术,它使分析人员能够迅速、一致、交互地从各个方面观察信息,以达到深入理解数据的目的,从各方面观察信息,也就是从不同的维度分析数据,因此 OLAP 也成为多个维度分析
星型模型:
事实和维度:
1.3 架构
1、REST Server:是一套面向应用程序开发的入口点,旨在实现针对 Kylin 平台的应用开发工作,此类应用程序可以提供查询、获取结果、触发 Cube 构建任务、获取元数据以及获取用户权限等等,另外可以通过 Restful 接口实现 SQL 查询
2、查询引擎(Query Engine):当 Cube 准备就绪后,查询引擎就能够获取并解析用户查询,它随后会与系统中的其它组件进行交互,从而向用户返回对应的结果
3、路由器(Routing):在最初设计时曾考虑过将 Kylin 不能执行的查询引导去 Hive 中继续执行,但在实践后发现 Hive与 Kylin 的速度差异过大,导致用户无法对查询的速度有一致的期望,很可能大多数查询几秒内就返回结果了,而有些查询则要等几分钟到几十分钟,因此体验非常糟糕,最后这个路由功能在发行版中默认关闭
4、元数据管理工具(Metadata):Kylin 是一款元数据驱动型应用程序,元数据管理工具是一大关键性组件,用于对保存在 Kylin 当中的所有元数据进行管理,其中包括最为重要的 Cube 元数据,其它全部组件的正常运作都需以元数据管理工具为基础,Kylin 的元数据存储在 HBase 中
5、任务引擎(Cube Build Engine):这套引擎的设计目的在于处理所有离线任务,其中包括 shell 脚本、Java API、MR 等,任务引擎对 Kylin 当中的全部任务加以管理与协调,从而确保每一项任务都能得到切实执行并解决其间出现的故障
1.4 特点
- 标准 SQL 接口:Kylin 是以标准的 SQL 作为对外服务的接口
- 支持超大数据集:Kylin 对于大数据的支撑能力可能是目前所有技术中最为领先的
- 亚秒级响应:Kylin 拥有优异的查询相应速度,这点得益于预计算,很多复杂的计算,比如连接、聚合,在离线的预计算过程中就已经完成,这大大降低了查询时刻所需的计算量,提高了响应速度
- 可伸缩性和高吞吐率:单节点 Kylin 可实现每秒 70 个查询,还可以搭建 Kylin 的集群
- BI 工具集成
- ODBC:与 Tableau、Excel、PowerBI 等工具集成
- JDBC:与 Saiku、BIRT 等 Java 工具集成
- RestAPI:与 JavaScript、Web 网页集成
- Zepplin:访问 Kylin 服务
2 安装部署
1、先决条件是必须安装 hadoop、hive、hbase、zookeeper
2、需要在 /etc/profile 文件中配置 HADOOP_HOME、HIVE_HOME、HBASE_HOME、并 source 使其生效
3、解压 apache-kylin-2.5.1-bin-hbase1x.tar.gz到 /opt/module
[djm@hadoop102 sorfware]$ tar -zxvf apache-kylin-2.5.1-bin-hbase1x.tar.gz -C /opt/module/
4、启动和关闭
[djm@hadoop102 kylin]$ bin/kylin.sh start
[djm@hadoop102 kylin]$ bin/kylin.sh stop
5、测试
username:ADMIN
password:KYLIN
3 快速入门
3.1 创建项目
3.2 创建 Model
3.3 创建 Cube
高阶模块(默认)
4 Cube 构建原理
4.1 构建流程
4.2 构建算法
4.2.1 逐层构建算法
一个 n 维的立方体由 2^(n-1) 个立方体组成,在逐层算法中,按维度逐层减少来计算,每个层级的计算都是基于其上一层的结果来计算的,当 0 层维度被计算出来的时候,整个 Cube 的计算就完成了
每一轮的计算都是一个 MapReduce 任务,且串行执行,n 维的 Cube,至少需要 n 次 MapReduce Job
算法优点:
- 充分利用了 MapReduce 的优点,处理了中间复杂的排序和 shuffle 工作,代码清晰简单,易于维护
- 受益于 Hadoop 的日趋成熟,此算法非常稳定,即便是集群资源紧张时,也能保证最终能够完成
算法缺点:
- 当 Cube 有比较多个维度度的时候,所需要的 MapReduce 任务也相应增加
- 由于 Hadoop 的任务调度需要耗费额外资源,特别是集群较庞大的时候,反复递交任务造成的额外开销会相当可观
- 由于 Mapper 逻辑中并未进行聚合操作,所以每轮 MR 的 shuffle 工作量都很大,导致效率低下
- 对 HDFS 的读写操作较多,由于每一层计算的输出会用做下一层计算的输入,这些 KV 需要写到 HDFS 上,当所有计算都完成后,Kylin 还需要额外的一轮任务将这些文件转成 HBase 的 HFile 格式,以导入到 HBase 中
4.2.2 快速构建算法
也被称作逐段(By Segment)或逐块(By Split)算法,从 1.5.x 开始引入该算法,该算法的主要思想是,每个 Mapper 将其所分配到的数据块,计算成一个完整的小 Cube 段(包含所有 Cuboid),每个 Mapper 将计算完的 Cube 段输出给Reducer 做合并,生成大 Cube,也就是最终结果
与旧算法相比,快速算法主要有两点不同:
- Mapper 会利用内存做预聚合,算出所有组合,Mapper 输出的每个Key 都是不同的,这样会减少输出到 Hadoop MapReduce 的数据量,Combiner 也不再需要
2)一轮 MapReduce 便会完成所有层次的计算,减少 Hadoop 任务的调配
5 Cube 构建优化
在没有采取任何优化措施的情况下,Kylin 会对每一种维度的组合进行预计算,每种维度的组合的预计算结果被称为Cuboid,假设有4个维度,我们最终会有 16 个 Cuboid 需要计算。
但在现实情况中,用户的维度数量一般远远大于 4 个,假设用户有 10 个维度,那么没有经过任何优化的 Cube 就会存在1024 个 Cuboid,而如果用户有 20 个维度,那么Cube 中总共会存在 1048576 个 Cuboid,虽然每个 Cuboid 的大小存在很大的差异,但是单单想到 Cuboid 的数量就足以让人想象到这样的 Cube 对构建引擎、存储引擎来说压力有多么巨大,因此,在构建维度数量较多的 Cube 时,尤其要注意 Cube 的优化。
5.1 衍生维度
衍生维度用于在有效维度内将维度表上的非主键维度排除掉,并使用维度表的主键(其实是事实表上相应的外键)来替代它们,Kylin 会在底层记录维度表主键与维度表其他维度之间的映射关系,以便在查询时能够动态地将维度表的主键翻译成这些非主键维度,并进行实时聚合。
虽然衍生维度具有非常大的吸引力,但是也不是说所有的维度表都适合衍生维度,如果从维度主建到某个维度的聚合工作量较大,不建议使用,时间换空间还是空间换时间,看业务需求权衡。
5.2 聚合组
5.2.1 强制维度
如果一个维度被定义为强制维度,那么整个分组中产生的 cubeid 必须包含该维度,每个分组中都可以有 0 个或多个强制维度。如果根据这个分组的业务逻辑,则相关的查询一定会在过滤条件或分组条件中,因此可以在该分组中把该维度设置为强制维度。
5.2.2 层级维度
每个层级中包含两个或多个维度,假设 D1、D2 被设置为层级维度,那么分组中的 cubeid 如果 D2 出现时,D1 必须也出现,但是 D1 可以单独出现,一般适用于日期、地址,每个分组中可以有0个、1个或多个层级,不同的层级之间不应当有共享的维度。如果根据这个分组的业务逻辑,则多个维度直接存在层级关系,因此可以在该分组中把这些维度设置为层级维度。
5.2.3 联合维度
每个联合维度包含两个或多个维度,如果某些列形成一个联合,那么在该分组产生的任何 Cuboid 中,这些联合维度要么一起出现,要么都不出现,每个分组中可以有 0 个或多个联合,但是不同的联合之间不应当有共享的维度(否则它们可以合并成一个联合),如果根据这个分组的业务逻辑,多个维度在查询中总是同时出现,则可以在该分组中把这些维度设置为联合维度。
这些操作可以在 Cube Designer 的 Advanced Setting 中的 Aggregation Groups 区域完成
5.3 RowKey 优化
Kylin 会把所有的维度按照顺序组合成一个完整的 RowKey,并且按照这个 RowKey 升序排列 Cuboid 中所有的行,设计良好的 RowKey 将更有效地完成数据的查询过滤和定位,减少 IO 次数,提高查询速度,维度在 RowKey 中的次序,对查询性能有显著的影响。
RowKey 的设计原则如下:
- 被用作 where 过滤的维度放在前边
- 基数大的维度放在基数小的维度前边
5.4 并发粒度优化
当 Segment 中某一个 Cuboid 的大小超出一定的阈值时,系统会将该 Cuboid 的数据分片到多个分区中,以实现 Cuboid数据读取的并行化,从而优化 Cube 的查询速度,具体的实现方式如下:
构建引擎根据 Segment 估计的大小,以及参数 kylin.hbase.region.cut 的设置决定 Segment 在存储引擎中总共需要几个分区来存储,如果存储引擎是 HBase,那么分区的数量就对应于 HBase 中的 Region 数量,kylin.hbase.region.cut 的默认值是 5.0,单位是 GB,也就是说对于一个大小估计是 50GB 的 Segment,构建引擎会给它分配 10 个分区,用户还可以通过设置 kylin.hbase.region.count.min、kylin.hbase.region.count.max 来决定每个 Segment 最少或最多被划分成多少个分区
由于每个 Cube 的并发粒度控制不尽相同,因此建议在 Cube Designer 的 Configuration Overwrites 中为每个 Cube 量身定制控制并发粒度的参数,假设将把当前 Cube 的 kylin.hbase.region.count.min 设置为 2,kylin.hbase.region.count.max设置为 100,这样无论 Segment 的大小如何变化,它的分区数量最小都不会低于 2,最大都不会超过 100,相应地,HBase 为了存储这个 Segment,也不会使用小于两个或超过 100 个的分区,我们还调整了默认的kylin.hbase.region.cut,这样 50GB 的 Segment 基本上会被分配到50个分区,相比默认设置,我们的 Cuboid可能最多会获得 5 倍的并发量
6 集成 BI 工具
6.1 JDBC
导入依赖:
<dependencies>
<dependency>
<groupId>org.apache.kylin</groupId>
<artifactId>kylin-jdbc</artifactId>
<version>2.5.1</version>
</dependency>
</dependencies>
编码:
package com.djm;
import java.sql.*;
public class TestKylin {
public static void main(String[] args) throws Exception {
//Kylin_JDBC 驱动
String KYLIN_DRIVER = "org.apache.kylin.jdbc.Driver";
//Kylin_URL
String KYLIN_URL = "jdbc:kylin://hadoop102:7070/FirstProject";
//Kylin的用户名
String KYLIN_USER = "ADMIN";
//Kylin的密码
String KYLIN_PASSWD = "KYLIN";
//添加驱动信息
Class.forName(KYLIN_DRIVER);
//获取连接
Connection connection = DriverManager.getConnection(KYLIN_URL, KYLIN_USER, KYLIN_PASSWD);
//预编译SQL
PreparedStatement ps = connection.prepareStatement("SELECT sum(sal) FROM emp group by deptno");
//执行查询
ResultSet resultSet = ps.executeQuery();
//遍历打印
while (resultSet.next()) {
System.out.println(resultSet.getInt(1));
}
}
}
6.2 Zepplin
1、解压 zeppelin-0.8.0-bin-all.tgz 到 /opt/module
[djm@hadoop102 sorfware]$ tar -zxvf zeppelin-0.8.0-bin-all.tgz -C /opt/module/
2、修改文件夹名称
[djm@hadoop102 module]$ mv zeppelin-0.8.0-bin-all/ zeppelin
3、启动
[djm@hadoop102 zeppelin]$ bin/zeppelin-daemon.sh start
4、访问