官网:http://kylin.apache.org/
Kylin-中国团队研发的,是第一个真正由中国人自己主导、从零开始、自主研发、并成为Apache顶级开源项目
Kylin的定位:对数据进行预计算/预处理,主要出现在辅助Hive组件(查询效率比较慢),提高查询效率。
Hive的性能比较慢,支持SQL,HBase的性能快,原生不支持SQL。
Kylin是将先将数据进行预处理,将预处理的结果放在HBase中。效率很高(将hive和hbase两个技术的优点结合到一起)
使用场景
用Hive将HDFS文件数据以关系数据方式存取,数据量巨大,每天有数G甚至数十G的数据增量导入,有10个以内较为固定的分析维度
核心思想
Kylin 的核心思想是利用空间换时间
Kylin 是一个 Hadoop 生态圈下的 MOLAP (多维立方体分析)系统,支持SQL语句,提供交互式的查询能力(交互式:强调的是查询返回速度的效率高/快),Cube 的概念,支持标准的JDBC查询方式,与 BI 工具可无缝整合。
联机事务处理OLTP、联机分析处理OLAP。
OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。
联机分析处理的用户是企业中的专业分析人员及管理决策人员,他们在分析业务经营的数据时,从不同的角度来审视业务的衡量指标是一种很自然的思考模式。例如分析销售数据,可能会综合时间周期、产品类别、分销渠道、地理分布、客户群类等多种因素来考量。
基本原理
在目前开源版本的实现中,构建完的数据是存储在 HBase 中的,在上面小节中,我们得到了一个能够查询 Cube 数据的逻辑执行计划,Calcite 框架会根据这个逻辑执行计划生成对应的物理执行计划,最终每个算子都会通过代码生成生成自己算子的可执行代码,这个过程是一个迭代器模型,数据从最底层的 TableScan 算子向上游算子流动,整个过程就像火山喷发一样,故又名 Volcano Iterator Mode。而这个 TableScan 生成的代码会从 HBase 中取出 Cube 数据,当数据返回到 Kylin 的 Query Server 端之后,再被上层的算子一层层消费。
Kylin On HBase瓶颈
这套方案对于简单的 SQL 并没有什么大问题,因为在精确匹配 Cuboid 的情况下,从 HBase 取回数据后,在 Kylin Query Server 端并不会做太多计算,但当一些比较复杂的查询,例如一句查询 join 了两个子查询,每个子查询都命中了各自的 cube,并在最外层做一些比较复杂的 Aggregate 操作,比如 COUNT DISTINCT 等,在这种情况下,Kylin Query Server 端不仅要从 HBase拉回大量的数据,并且还要在 Kylin Query Server 端计算 Join/Aggregate 等非常耗时耗资源的操作,当数据量变大,Kylin 的Query Server 端就可能会 OOM,解决的方式是提高 Query Server 端的内存,但这是个垂直扩容的过程,这就成了一个单点瓶颈,而大数据方案中存在单点瓶颈,是一个非常严重的问题,可能直接导致公司在架构选型的时候一键 pass 掉这个方案。
另外这套方案在使用中还有很多其他的局限:
- 例如 HBase 的运维是出了名的难,一旦 HBase 性能不好,那么可想而知 Kylin 的性能也不会好。
- HBase 的资源隔离能力也比较弱,当某个时刻有比较大的负载的时候,其他使用 HBase 的业务也会受到影响,体现到 Kylin 可能会是查询的性能比较不稳定,benchmark 会有毛刺,解释起来比较麻烦并且需要集群 metric 的支持,对前线人员要求比较高。
- HBase 里存储的都是经过编码后的 Byte Array 类型,序列化反序列化的开销也不能忽视。而对于我们开发人员来说,Calcite 代码生成比较难以调试,并且我们 HBase 的技能树修的比较少,想对 HBase 做源码级别的性能改进也比较困难。
Kylin的总体架构
Kylin 依赖于 Hadoop、Hive、Zookeeper 和 Hbase
准备依赖的Hbase1.1.1(只安装一个节点)
说明:Hbase 1.1.1只在一个节点安装。
修改hbase-env.sh 添加JAVA_HOME环境变量
export JAVA_HOME=/export/servers/jdk1.8.0_141/
export HBASE_MANAGES_ZK=false
修改hbase-site.xml,添加以下配置。
<configuration>
<property>
<name>hbase.rootdir</name>
<value>hdfs://node1:8020/hbase_1.1.1</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- 0.98后的新变动,之前版本没有.port,默认端口为60000 -->
<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2181</value>
</property>
<property>
<name>hbase.master.info.port</name>
<value>60010</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>node1,node2,node3</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/export/servers/zookeeper-3.4.9/zkdatas</value>
</property>
<property>
<name>hbase.thrift.support.proxyuser</name>
<value>true</value>
</property>
<property>
<name>hbase.regionserver.thrift.http</name>
<value>true</value>
</property>
</configuration>
在hbase conf目录中创建core-site.xml和hdfs-site.xml软连接,或拷贝
修改regionservers配置文件
node01
配置环境变量
export HBASE_HOME=/export/servers/hbase-1.1.1
export PATH=:$HBASE_HOME/bin:$PATH
刷新环境变量
source /etc/profile
删除zk历史数据
# 进入到 zkCli中
/export/servers/zookeeper-3.4.9/bin/zkCli.sh
# 执行删除
rmr /hbase
启动
bin/start-hbase.sh
验证
List
Kylin安装部署
1、上传并解压
tar -zxf /export/softwares/apache-kylin-2.6.3-bin-hbase1x.tar.gz -C /export/servers/
2、拷贝hadoop\hive\hbase\spark核心泪痣文件到kylin的conf目录
cp /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/hdfs-site.xml .
cp /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/core-site.xml .
cp /export/servers/hive-1.1.0-cdh5.14.0/conf/hive-site.xml .
cp /export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0/conf/spark-defaults.conf.template .
3、添加hadoop\hive\hbase\spark路径到bin/kylin.sh
export HADOOP_HOME=/export/servers/hadoop-2.6.0-cdh5.14.0
export HIVE_HOME=/export/servers/hive-1.1.0-cdh5.14.0
export HBASE_HOME=/export/servers/hbase-1.1.1
export SPARK_HOME=/export/servers/spark-2.2.0-bin-2.6.0-cdh5.14.0
4、配置conf/kylin.properties
[hide reply_to_this="true"]conf[/hide]
修改 配置文件\kylin.properties 中HDFS的路径
上传到 Linux的 Kylin/conf文件夹中
5、初始化kylin在hdfs上的数据路径
hadoop fs -mkdir -p /apps/kylin
6、启动集群
1、启动zookeeper
2、启动HDFS
3、启动YARN集群
4、启动HBase集群
5、启动 metastore
nohup hive --service metastore &
6、启动 hiverserver2
nohup hive --service hiveserver2 &
7、启动Yarn history server
mr-jobhistory-daemon.sh start historyserver
8、启动spark history server【可选】
sbin/start-history-server.sh
7、启动kylin
./kylin.sh start
s
7、登录Kylin
url | http://IP:7070/kylin |
---|---|
默认用户名 | ADMIN |
默认密码 | KYLIN |
准备测试数据
创建数据库、表、加载数据
create table dw_sales(id string,date1 string,channelId string, productId string, regionId string,amount int,price double)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' stored as textfile;
-- 2、渠道表:dim_channel
-- channelId 渠道ID
-- channelName 渠道名称
create table dim_channel(channelId string, channelName string )ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' stored as textfile;
-- 3、产品表:dim_product
create table dim_product(productId string, productName string )ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' stored as textfile;
--4、区域表:dim_region
create table dim_region(regionId string,regionName string)ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' stored as textfile;
-- 导入数据
LOAD DATA LOCAL INPATH '/opt/kylindatas/dw_sales_data.txt' OVERWRITE INTO TABLE dw_sales;
LOAD DATA LOCAL INPATH '/opt/kylindatas/dim_channel_data.txt' OVERWRITE INTO TABLE dim_channel;
LOAD DATA LOCAL INPATH '/opt/kylindatas/dim_product_data.txt' OVERWRITE INTO TABLE dim_product;
LOAD DATA LOCAL INPATH '/opt/kylindatas/dim_region_data.txt' OVERWRITE INTO TABLE dim_region;
测试业务查询效率
需求:按照日期和渠道查看日期以及对应的交易金额和交易数量。
Sql=
select
date1, sum(price) as total_money, sum(amount) as total_amount
from
dw_sales
group by
date1,channelid;
以上SQL使用hive 查询两次效率为
1、2718 2912 20 12 32-29-27
红色字体是指标/度量?还是维度?
答案:指标/度量【到底要看什么?获取什么?】
蓝色字体是指标/度量?还是维度?
答案:维度【怎么看!怎么获取!】
需求:根据性别、身高、体重 查看大数据班级同学的姓名、性别、家庭住址。
指标是?姓名、性别、家庭住址
维度值?性别、身高、体重
结论:需求决定哪些是维度,哪些是指标。
使用kylin对数据进行预计算流程
1、创建项目(Project)
2、创建数据源(DataSource)
指定有哪些数据需要进行数据分析
3、创建模型(Model)
指定具体要对哪个事实表、那些维度进行数据分析
4、创建立方体(Cube)
指定对哪个数据模型执行数据预处理,生成不同维度的数据
5、执行构建、等待构建完成
6、再执行SQL查询,获取结果
从Cube中查询数据
实施:
1、创建项目(Project)
2、创建数据源(DataSource)
3、创建模型(Model)
设置model名称
4、创建立方体(Cube)
- 执行构建、等待构建完成
6、再执行SQL查询,获取结果
从Cube中查询数据
项目/model/cube的关系
设置维度---维度就是sql中GroupBY后面的字段.
设置指标/度量---指标/度量就是sql中select 后面的字段.
整个配置过程都来源于SQL,来源于需求。
配置过程
创建项目—引入数据—创建模型—创建cube –编译 – 查询
查看最终计算完毕的结果数据
按照订单渠道名称统计订单总额/总数量
哪个是指标??总额/总数量
哪个是维度??渠道
select
t2.channelid,
t2.channelname,
sum(t1.price) as total_money,
sum(t1.amount) as total_amount
from
dw_sales t1
inner join dim_channel t2
on t1.channelid = t2.channelid
group by t2.channelid, t2.channelname
创建cube选择维度
SQL和Cube之间的关系??
1、根据什么写SQL?? 需求
需求决定SQL
2、数据仓库员基于Hive,为什么不用hive直接推介用户/领导(线上系统)
Hive效率慢
3、Hive特别慢,怎么解决慢的问题???
想办法加速查询效率!!
Kylin就是加速Hive查询效率的有效手段。
最终:SQL是确定,不能变的。加速查询效率使用kylin。
所以:根据SQL创建Cubeb(Cube来源于SQL,辅助SQL),先有sql后有cube
为什么极大的提高了效率?
原因是,kylin将业务需要的数据全局提前计算出来,并保存。当用户查询时,直接在计算的结果中读取,不需要重新计算。
没有使用kylin前,SQL是需要计算的。
有使用kylin后,SQL不需要计算,变成了查询的。
好处:查询速度快
弊端:需要花费时间提前预计算。
Kylin的工作原理
Apache Kylin的工作原理本质上是 MOLAP(多维立方体分析)
维度就是观察数据的角度,通常是SQL中的group by后面的字段
度量就是被聚合的统计值,也是聚合运算的结果,通常是SQL中的select 后面的字段经过聚和的结果。
N个维度,随机组合可能出现的组合方式有多少种???
2的N次方-1, N代表维度的个数。
在kylin中没有维度也算一个维度,所以2的N次方。
- 每一种维度的组合(12,24,124,3)称为Cuboid(立方形)
所有维度组合的Cuboid作为一个整体,被称为Cube(立方体)
- 一个数据表或数据模型上的字段就它们要么是维度,要么是度量(可以被聚合)
工作原理是对数据模型做Cube预计算,并利用计算的结果加速查询
工作过程如下。
- 指定数据模型,定义维度和度量
- 预计算Cube,计算所有Cuboid并保存为物化视图(存储到hbase中)
- 执行查询时,读取Cuboid,运算,产生查询结果
技术架构
Apache Kylin系统可以分为在线查询和离线构建两部分。
在线查询
离线构建
理解Cube、Cuboid与Segment的关系
Kylin将Cube划分为多个Segment(对应就是HBase中的一个表),每个Segment用起始时间和结束时间来标志(全量数据使用FULL_BUILD)。Segment代表一段时间内源数据的预计算结果。
全量和增量的区别
- 全量构建Cube
- 查询引擎只需向存储引擎访问单个Segment所对应的数据,无需进行Segment之间的聚合
增量构建Cube
- 由于不同时间的数据分布在不同的Segment之中,查询引擎需要向存储引擎请求读取各个Segment的数据
- 增量构建的Cube上的查询会比全量构建的做更多的运行时聚合,通常来说增量构建的Cube上的查询会比全量构建的Cube上的查询要慢一些。
小数据量的Cube,或者经常需要全表更新的Cube,使用全量构建。
对于大数据量的Cube,包含两年历史数据的Cube,如果需要每天更新使用增量构建。
在全量构建中,Cube中只存在唯一的一个Segment,
增量构建只会导入新Segment指定的时间区间内的原始数据,并只对这部分原始数据进行预计算。
创建cube结束后,在build时设置计算数据的日期
第一天同步成功
新计算下一个日期的数据
根据层量同步方案,得出一个结论。结论:每天成成一个Segment,一年就有365个Segment。
当用户查询时,系统不知道数据在哪个Segment中,所以需要扫描所有的Segment(扫描356个表),扫描多个表/多个Segment会降低数据查询效率。【增量方案带来的问题】
补充:文件越多效率越慢。
1个文件10G和10000个文件共10G 读取一个文件更快(寻址开销、频繁发开关闭) 一个文件夹内的文件特别多,这个文件夹打开的时间就会特别长。【xxxxxx卫星应用中心】 当系统越来越慢,越来越慢,越来越慢,越来越慢,有可能是某一个目录中的数据没有及时的清空或删除。 |
管理Cube碎片(Segment)
方案:(目标:减少Segment的数量)
合并Segment!
手动合并
选中需要合并的Segment,可以同时合并多个Segment,但是这些Segment必须是连续的
合并过程中不允许提交这个Cube上任何类型的其他构建任务,但是合并的Segment仍然处于可用的状态。
自动合并
合并逻辑:一个segment可以存储一天的数据也可以存储多天的数据,数据内的天数达到了阈值就跳过,没有达到阈值就合并到这个阈值,没满足不合并。
如果不合并,就会产生N个天的segment,合并就会大大减少segment的数量。
部署
设置阈值,可以使一个也可以使多个。
运行完毕以后,生成一天的数据
提交下一个一天的数据(1014-1015)
若设置多层次的合并级别,最好是每个层次之间是整倍数关系
删除Segment!
手动删除
自动删除
使用JDBC连接操作Kylin
使用JDBC链接kylin直接使用。不需要关注kylin中model的名称cube的名称,以及两者之间的关系
import java.sql.*;
public class KylinDemo {
public static void main(String[] args) throws Exception {
// 1、加载驱动
Class.forName("org.apache.kylin.jdbc.Driver");
// 2、创建Connection连接对象
// 连接字符串:jdbc:kylin://ip地址:7070/项目名称(project)
// demo01:kylin中Project的名称
Connection connection = DriverManager.getConnection("jdbc:kylin://node01:7070/demo01",
"ADMIN",
"KYLIN");
// 3、创建Statement对象,并执行executeQuery,获取ResultSet
Statement statement = connection.createStatement();
// 构建SQL和语句
String sql = "select\n" +
"t2.channelid,\n" +
"t2.channelname,\n" +
"sum(t1.price) as total_money,\n" +
"sum(t1.amount) as total_amount\n" +
"from \n" +
"dw_sales t1\n" +
"inner join dim_channel t2\n" +
"on t1.channelid = t2.channelid\n" +
"group by t2.channelid, t2.channelname\n";
ResultSet resultSet = statement.executeQuery(sql);
// 4、打印ResultSet
while(resultSet.next()) {
// 4.1 渠道ID
String date1 = resultSet.getString("channelid");
// 4.2 渠道名称
String regionname = resultSet.getString("channelname");
// 4.3 总金额
String productname = resultSet.getString("total_money");
// 4.4 总数量
String total_money = resultSet.getString("total_amount");
System.out.println(date1 + " " + regionname + " " + productname + " " + total_money );
}
connection.close();
}
}
KYlin优化
Cuboid剪枝优化
对于业务永远不会使用的维度组合(cuboid)不进行预计算。
目前维度有四个,四个维度组成的可能性就16种,kylin会计算所有的可能【穷举法】,并将结果存储到Hbase,会使用大量存储空间。那么每一种都会被使用吗?
实际生产中,有部分cuboid是永远使用不到的,这些不使用的cuboid就可以不预计算。
Kylin的核心思想:空间换时间
可以接受的膨胀比范围0%~1000%之间
具体优化的操作:
- 需要选择跳过那些“多余”的Cuboid --》结合业务来判断哪些cuboid是多余
- 有的Cuboid因为查询样式的原因永远不会被查询到,因此显得多余--》层级维度,省市区,年月日
- 有的Cuboid的能力和其他Cuboid接近,因此显得多余 --》衍生维度
查看cuboid数量
bin/kylin.sh org.apache.kylin.engine.mr.common.CubeStatsReader CUBE_NAME
# CUBE_NAME 想要查看的Cube的名字
衍生维度不适用的场景:
- 如果从维度表主键到某个维度表维度所需要的聚合工作量非常大,此时作为一个普通的维度聚合更合适,否则会影响Kylin的查询性能
第一种情况
2*2*2*2*2-1=31
第二种情况
2*2*2-1=7
bin/kylin.sh org.apache.kylin.engine.mr.common.CubeStatsReader CUBE_NAME
第一种情况创建的cuboid数量会比第二种情况创建的cuboid数量多
所以使用衍生维度能够大量减少计算任务和空间的占用。
聚合组
- 聚合组(Aggregation Group)是一种更强大的剪枝工具
- 强制维度(Mandatory)
- 如果一个维度被定义为强制维度,那么这个分组产生的所有Cuboid中每一个Cuboid都会包含该维度。所有cuboid必须包含的维度,不会计算不包含强制维度的cuboid
- 包含了这个维度的组合就计算,不包含就不计算。
- 层级维度(Hierarchy)
- 多个维度直接存在层级关系,因此可以在该分组中把这些维度设置为层级维度
- 从2的N次方减少到N+1
- 联合维度(Joint)
- 每个联合中包含两个或更多个维度,如果某些列形成一个联合,那么在该分组产生的任何Cuboid中,这些联合维度要么一起出现,要么都不出现
- 从2的N次方减少到1 (班级,专业,学校=7 班级,专业,学校 1 )
AGG_CUBE2使用了层级组设置了 国家-省-市,年-月-日
AGG_CUBE没有任何设置
最终结果如下
Cube
Cube2(设置层级)
使用kylin对数仓的数据进行加速
Hive效率
select
paytype,
count(distinct orderid) total_cnt,
sum(goodsprice) total_money
from
itcast_dw.TMP_ORDER_GOODS_CAT_ORG
group by paytype;
19.811
select
'9' as paytype,
count(distinct orderid) total_cnt,
sum(goodsprice) total_money
from
itcast_dw.TMP_ORDER_GOODS_CAT_ORG;
12.982
使用kylin创建cube获得查询效率
select
paytype,
count(distinct orderid) total_cnt,
sum(goodsprice) total_money
from
itcast_dw.TMP_ORDER_GOODS_CAT_ORG
group by paytype;
7 0.1 0.00
使用kylin前后查询效率的对比
使用之前:19.811
使用之后:7-------0.1
使用前:15.418 s
使用后:0.81s
kylin将业务需要的数据全局提前计算(预计算)出来,并保存。
文章评论