Kylin是 Apache开源的分布式分析引擎,提供Hadoop、Spark、Flink之上的的SQL查询接口和**多维分析(OLAP)**能力,支持超大规模数据。
即席查询有两种:Kylin是 预计算。Presto是 基于内存
OLAP(online analytical processing)是一种软件技术,使分析人员能够迅速、一致、交互的从各个方面观察讯息,OLAP也称为多维分析!
OLAP分为两种:ROLAP和MOLAP
ROLAP(Relational OLAP):基于关系型数据库,不需要预计算。
MOLAP(multidimensional OLAP):基于多维数据集,需要预计算。
MOLAP基于多数据集,一个多维数据集称为一个OLAP Cube
事实表&维度表
维度&度量
(1)支持超大规模数据集
(2)亚秒级响应
(3)标准SQL接口
(4)可伸缩和高吞吐量:可以搭建集群
(5)BI工具集成
(1)REST Server(查询)
用来暴露接口,通过该接口可以提供查询、获取结果、触发cube构建任务、获取元数据、获取用户权限等。
(2)Query Engine(查询)
查询引擎,当cube准备就绪后,查询引擎能够获取并解析用户查询。
(3)Routing路由器
Kylin只能用来查询cube设计好的结果。对于一些查询并不能直接查询,早期的提供了一个路由层将这种不能使用kylin的查询,路由到hive去执行,但是这样的查询速度就特别慢了。发行版中路由功能默认关闭!
(4)Metadata元数据
Kylin的元数据都保存在HBase中,保存了Kylin的所有元数据,其中最重要的是cube元数据。
(5)Cube Build Engine任务引擎
任务引擎对Kylin当中的全部任务加以管理与协调,从而确保每一项任务都能得到切实执行并解决其间出现的故障。
安装Kylin前需要先部署好Hadoop、Hive、Zookeeper、HBase;并且需要配置环境变量(/etc/profile.d/my_env.sh )
这是因为Kylin会根据环境变量去加载所依赖的框架,不然的话要去Kylin配置这些环境
#HADOOP_HOME
export HADOOP_HOME=/opt/module/hadoop-3.1.3
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
#HIVE_HOME
export HIVE_HOME=/opt/module/hive
export PATH=$PATH:$HIVE_HOME/bin
#HBASE_HOME
export HBASE_HOME=/opt/module/hbase
export PATH=$PATH:$HBASE_HOME/bin
然后需要source让环境变量生效。
步骤1:上传Kylin安装包apache-kylin-3.0.2-bin.tar.gz到/opt/software/kylin
步骤2:解压安装包
[atguigu@hadoop102 sorfware]$ tar -zxvf apache-kylin-3.0.2-bin.tar.gz -C /opt/module/
[atguigu@hadoop102 module]$ mv /opt/module/apache-kylin-3.0.2-bin /opt/module/kylin
兼容性问题1
Hive3.1.2和我们使用的Spark3.0.0版本,有些API不能兼容!
解决的方式1:使用所支持的对应版本;
解决的方式2:下载源码,然后编译源码,将旧的过期的API替换成新的。
兼容性问题2
Kylin所依赖的API版本,和Spark里面所依赖的API版本不一样,这样Kylin启动时就会有两个同名的类!会根据加载顺序,如果加载了过期的依赖,那么就会报错!
解决方法:排除掉其中一个API
★排除冲突的jar包
修改/opt/module/kylin/bin/find-spark-dependency.sh,排除冲突的jar包,需要增加的内容:! -name ‘*jackson*’ ! -name ‘*metastore*’。注意前后的空格!!!
步骤1:启动Kylin之前,需要先启动Hadoop(hdfs、yarn、jobhistoryserver)、Zookeeper、HBase
步骤2:启动Kylin
[atguigu@hadoop102 kylin]$ bin/kylin.sh start
步骤3:登录web页面
http://hadoop102:7070/kylin
用户名为:ADMIN,密码为:KYLIN
步骤4:关闭Kylin
[atguigu@hadoop102 kylin]$ bin/kylin.sh stop
Kylin多维分析:
(1)如何使用Kylin计算
(2)如何使用Kylin查询
导入Hive表:
步骤1:new model
步骤2:model名称
步骤3:选择事实表、维度表
①事实表
②维度表,并指定事实表和维度表的关联条件
步骤4:选择维度字段
选择维度字段,可以从事实表中选择,也可以从维度表中选择。
步骤5:选择度量值
度量值只能从事实表中选择!
步骤6:指明分区字段(仅支持时间分区)和过滤条件
步骤1:填写cube信息,选择上面的model
步骤2:选择Kylin查询所需要的维度字段
normal普通维度:就是普通的维度
derived衍生维度:选择的并不是真正的维度,而是所在维度表的主键(事实表的外键);目的是为了减少计算量,加快预计算。但是可能会影响查询效率。不建议使用~
步骤3:选择所需度量值
可以单个添加度量值,也可以批量添加度量值~
步骤4:自动合并设置
cube自动合并设置,cube需按照日期分区字段每天进行构建,每次构建的结果会保存在HBase中的一张表中,如果时间长了,那么要查询会从很多表中查询,效率很差。
为了提高查询效率,需要将每日的cube进行合并,默认是7天一小合并,28天一大合并。
步骤5:Kylin高级配置(优化相关,暂时跳过)
步骤6:Kylin相关属性配置覆盖
永久有效的配置,在/opt/module/kylin/conf/kylin.properties中配置。
步骤7:构建Cube(计算)
步骤8:选择要构建的时间区间
步骤9:点击Monitor查看构建进度
①每日全量维度表及拉链表重复key的问题
②错误原因
上面model中的维度表:dwd_dim_user_info_his为拉链表、dwd_dim_sku_info为每日全量表。
使用整张表作为维度表,必然会出现订单表中同一个user_id或者sku_id对应多条数据的问题。
③解决方案1:创建临时表
在hive中创建维度表的临时表,该临时表只保存最新的一份完整的数据,在kylin中创建model时,选择临时表作为维度表。
④解决方案2:创建视图view
使用视图view实现上面相同功能。
步骤1:创建拉链维度表的视图(去重)
create view dwd_dim_user_info_his_view as select * from dwd_dim_user_info_his where end_date='9999-99-99';
步骤2:创建每日全量表的视图(去重)
--全量维度表视图
create view dwd_dim_sku_info_view as select * from dwd_dim_sku_info where dt=date_add(current_date,-1);
--当前情形我们先创建一个2020-06-16的视图
create view dwd_dim_sku_info_view as select * from dwd_dim_sku_info where dt='2020-06-16';
步骤3:删除discard掉前面的job,然后drop掉前面的job、cube、module、表,添加新的view
步骤4:重新创建model、cube
步骤5:查询结果
select
ui.gender,
si.tm_name,
dp.region_name,
sum(ORIGINAL_AMOUNT_D)
from
dwd_fact_order_detail od
join
dwd_dim_user_info_his_view ui
on
od.user_id=ui.id
join
dwd_dim_sku_info_view si
on
od.sku_id=si.id
join
dwd_dim_base_province dp
on
od.province_id=dp.id
group by
ui.gender,si.tm_name,dp.region_name;
Kylin也是离线计算,也要每天都跑。每天都要提交构建任务。构建任务是手动创建cube,build,提交日期。
Kylin任务交给azkaban调度。(Kylin的构建任务 封装到一个脚本中。)
这样我们就能将构建cube的命令写道脚本中,将脚本就可以交给azkaban或者oozie去调度了。
官网地址:http://kylin.apache.org/
其中curl -X POST 指明发送的请求的方式。
-H 是请求的请求头Header,"Authorization是认证。xxxxx位置是:Kylin的用户名和密码,用户名:密码不能明文的方式写在这里,要使用base64加密算法。
curl -X POST -H "Authorization: Basic QURNSU46S1lMSU4=" -H "Content-Type: application/json" -d '{ "sql":"select ui.gender,si.tm_name,dp.region_name,sum(ORIGINAL_AMOUNT_D) from dwd_fact_order_detail od join dwd_dim_user_info_his_view ui on od.user_id=ui.id join dwd_dim_sku_info_view si on od.sku_id=si.id join dwd_dim_base_province dp on od.province_id=dp.id group by ui.gender,si.tm_name,dp.region_name;", "project":"gmall" }' http://hadoop102:7070/kylin/api/query
可以在任何一台节点上执行这个命令:很快就能响应结果
- curl -X PUT 指明发送请求的方式为PUT
- -H 头信息,认证;内容类型json格式
- startTime开始的时间戳,毫秒;endTime结束的时间戳
- http://:/kylin/api/cubes/{构建的cube的名称}/build
curl -X PUT -H "Authorization: Basic XXXXXXXXX" -H 'Content-Type: application/json' -d '{"startTime":'1423526400000', "endTime":'1423612800000', "buildType":"BUILD"}' http://<host>:<port>/kylin/api/cubes/{cubeName}/build
构建Cube的脚本
#!/bin/bash
cube_name=order_cube
do_date=`date -d '-1 day' +%F`
#获取00:00时间戳
start_date_unix=`date -d "$do_date 08:00:00" +%s`
start_date=$(($start_date_unix*1000))
#获取24:00的时间戳
stop_date=$(($start_date+86400000))
curl -X PUT -H "Authorization: Basic QURNSU46S1lMSU4=" -H 'Content-Type: application/json' -d '{"startTime":'$start_date', "endTime":'$stop_date', "buildType":"BUILD"}' http://hadoop102:7070/kylin/api/cubes/$cube_name/build
维度,就是观察数据的角度
度量,就是被聚合(观察)的统计值,也就是聚合运算的结果
Cuboid,每种维度组合jjiu是一个Cuboid
Cube,15个Cuboid整体就是一个Cube
Cube在HBase中的存储是以K-V的形式存储的,K是coboid+维度字典表的维度值,V就是聚合值
其中coboid,只要有一个条件就是1
特点:稳定,但是速度慢,原因是多个MR串行运行。
特点是 ,速度快,基于内存。但是相对稳定性就差一些。
衍生维度是优化计算,通过减少计算量的方式 加快预计算。
**原理:**将维度表的非主键维度排除掉,使用维度表的主键(事实表的外键)来替代。
案例:
如果是A表:a,B表:b1,b2,C表:c。这样一共有4个维度,使用nomal方式:会有15个cuboid
如果使用derived方式,就不使用这四个维度,而是使用对应事实表的外键,会有7个cuboid
问题:
虽然使用衍生维度会减少计算,但是会影响查询。因为像上图,最后会对查询的结果,再次聚合。
衍生维度使用场景
一般都不建议使用衍生维度,如果是计算时间不够了,可以使用衍生维度,因为降低计算时间。
什么时候不建议使用衍生维度?
维度表中的主键和维度字段的值相差太大,不建议使用。
比如:userid(百万条) —> gender(2条),最后有较多的聚合。
聚合组也是优化计算。聚合组(是Aggregation group)是一种强大的剪枝工具。
如果一个维度被定义为强制维度,那么这个分组产生的所有cuboid种的所有cuboid都会包含该维度。
比如年、月、日;省、市、县这样的维度都是由层级关系的。
有些维度的组合是没有意义的,比如年-日,所以这样的就不需要做统计了。
每个联合种包含两个或更多个维度。那么在所有的cuboid种这些联合维度,要么一起出现,要么都不出现。
Kylin会把所有的维度根据维度字典表的数字 按照顺序组合成一个完整的Rowkey。
Rowkey的设计原则:(优化查询)
什么意思呢?
如果是下图这样的查询,如果Rowkey的顺序是A+B,那么查询的结果就是根据rowkey的字典序排列,那么A字段会排在前面,这样会出现间隔,会影响查询效率!
但是把过滤条件B放在前面,那么查询的时候,会将结果排在一起。可以提高查询效率。
当ABCD四个维度,降维成三维Cuboid为1110和1101的时候,如果再降成二维1100,那么可以从1110降、也可以从1101降,这个时候,是从一个三维降到二维即可!那么选择哪个?
kylin选择Cuboid小的,Cuboid小就说明AB相同的情况下D的基数要比C小,那么计算量也就小,所以Kylin的rowkey要将基数大的维度放再基数小的维度前面。
也是在第五步 Advanced Setting种设置中调整rowkey的顺序
并发粒度优化,其实就是HBase分区的优化
--HBase
在HBase中,一张表有可能会被分成多个Region,那么是怎么分成多个region的呢?
1 达到自动分裂的阈值 就自动分裂(HBase自动分裂的阈值是10G,也就是一个region超过10G就会分裂)
2 预分区(配置Rowkey),提前设置多少个分区数,配合上Rowkey的设计,让数据根据rowkey进入到不同的分区中
--Kylin
在Kylin中一个Segment其实就是HBase中的一张表
Kylin如何优化分区的呢?
1 通过参数"kylin.hbase.region.cut"设置region分裂的阈值(HBase默认10G、Kylin默认5G)
2 通过参数"kylin.hbase.region.count.min",设置分区的个数(预分区)
-- kylin.hbase.region.count.min(默认为1)
-- kylin.hbase.region.count.max(默认为500)
Kylin通过上面两个配置参数来决定每个Segment最少或最多被划分成多少个分区
可以与Kylin结合使用的可视化工具很多,例如:
ODBC:与Tableau、Excel、PowerBI等工具集成
JDBC:与Saiku、BIRT等Java工具集成
RestAPI:与JavaScript、Web网页集成
Kylin开发团队还贡献了Zepplin的插件,也可以使用Zepplin来访问Kylin服务。
步骤1:新建项目并导入依赖
<dependencies>
<dependency>
<groupId>org.apache.kylingroupId>
<artifactId>kylin-jdbcartifactId>
<version>3.0.2version>
dependency>
dependencies>
步骤2:编码
- 获取Kylin JDBC驱动
- 获取Kylin URL
- 获取Kylin 的用户名和密码
- 获取JDBC连接
- 编译SQL
- 执行SQL查询
- 遍历打印结果
public class JDBCTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//Kylin_JDBC 驱动
String KYLIN_DRIVER = "org.apache.kylin.jdbc.Driver";
//Kylin_URL
String KYLIN_URL = "jdbc:kylin://hadoop102:7070/gmall";
//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\n" +
" si.tm_name,\n" +
" dp.region_name,\n" +
" sum(ORIGINAL_AMOUNT_D)\n" +
"from\n" +
" dwd_fact_order_detail od\n" +
"join\n" +
" dwd_dim_user_info_his_view ui\n" +
"on\n" +
" od.user_id=ui.id\n" +
"join\n" +
" dwd_dim_sku_info_view si\n" +
"on\n" +
" od.sku_id=si.id\n" +
"join\n" +
" dwd_dim_base_province dp\n" +
"on\n" +
" od.province_id=dp.id\n" +
"group by\n" +
" ui.gender,si.tm_name,dp.region_name;");
//执行查询
ResultSet resultSet = ps.executeQuery();
//遍历打印
while (resultSet.next()) {
System.out.println(resultSet.getString(1)+ ":" + resultSet.getString(2)+":"+resultSet.getBigDecimal(3));
}
}
}
步骤3:查询结果
Zeppelin就是BI工具,集成各种各样的数据,执行查询语句,将结果转换成图形。
步骤1:将zeppelin的安装包上传到/opt/software
步骤2:将安装包解压到/opt/module/路径下
[atguigu@hadoop102 sorfware]$ tar -zxvf zeppelin-0.8.0-bin-all.tgz -C /opt/module/
# 修改名称
[atguigu@hadoop102 module]$ mv zeppelin-0.8.0-bin-all/ zeppelin
步骤3:修改zeppelin的端口号
为什么要修改zeppelin的端口号?
zeppelin默认的端口号是8080,但是Zookeeper在3.5版本leader也会占用8080端口,如果zookeeper选举的leader和zeppelin在一个节点上,就会端口冲突了,需要先去修改zeppelin的端口号。
[atguigu@hadoop102 zeppelin]$ cd conf/
[atguigu@hadoop102 conf]$ mv zeppelin-site.xml.template zeppelin-site.xml
[atguigu@hadoop102 conf]$ vim zeppelin-site.xml
# 查找port
修改为9090
步骤4:启动zeppelin
方式1:阻塞前台
[atguigu@hadoop102 zeppelin]$ bin/zeppelin.sh start
方式2:后台启动
[atguigu@hadoop102 zeppelin]$ bin/zeppelin-daemon.sh start
步骤1:登录web页面
步骤2:配置kylin的解释器
步骤3:对接kylin,创建note
步骤4:使用zeppelin