文章目录
一、Kylin4.x
1、Kylin概述
1.1 定义
Apache Kylin 是一个开源的分布式分析引擎,提供 Hadoop/Spark 之上的 SQL 查询接口及多维分析(OLAP)能力以支持超大规模数据,最初由 eBay Inc 开发并贡献至开源社区。它能在亚秒内查询巨大的 Hive 表。
OLAP(online analytical processing)是一种软件技术,它使分析人员能够迅速、一致、交互地从各个方面观察信息,以达到深入理解数据的目的。从各方面观察信息,也就是从不同的维度分析数据,因此OLAP也成为多维分析。也包括ROLAP(Relational OLAP)和MOLAP(Multidimensional OLAP),前者基于关系型数据库,不需要预计算;后者基于多维数据集,需要预计算
1.2 Kylin 架构
- REST Server
REST Server 是一套面向应用程序开发的入口点,旨在实现针对 Kylin 平台的应用开发工作。 此类应用程序可以提供查询、获取结果、触发 cube 构建任务、获取元数据以及获取用户权限等等。另外可以通过Restful 接口实现 SQL 查询。
- 查询引擎(Query Engine)
当 cube 准备就绪后,查询引擎就能够获取并解析用户查询。它随后会与系统中的其它组件进行交互,从而向用户返回对应的结果。 Kylin4.0 将 Spark 作为查询引擎。
- 路由层(Routing)
在最初设计时曾考虑过将 Kylin 不能执行的查询引导去 Hive 中继续执行,但在实践后发现 Hive 与 Kylin 的速度差异过大,导致用户无法对查询的速度有一致的期望,很可能大多数查询几秒内就返回结果了,而有些查询则要等几分钟到几十分钟,因此体验非常糟糕。最后这个路由功能在发行版中默认关闭。
- 元数据管理工具(Metadata)
Kylin 是一款元数据驱动型应用程序。元数据管理工具是一大关键性组件,用于对保存在 Kylin 当中的所有元数据进行管理,其中包括最为重要的 cube 元数据。其它全部组件的正常运作都需以元数据管理工具为基础。 Kylin4.0 的元数据存储在 MySQL 中
- 任务构建引擎(Cube Build Engine)
kylin4.0 的构建引擎从 MR 替换为 Spark,速度更快。使用户能够快速得到想要的 Cube数据。构建引擎最终得到的数据存放到 Parquet 文件当中,然后让用户可以更好的使用SparkSQL 查询引擎去读取 Cube 数据
1.3 Kylin 特点
Kylin 的主要特点包括支持 SQL 接口、支持超大规模数据集、亚秒级响应、可伸缩性、高吞吐率、BI 工具集成等
- 标准 SQL 接口:Kylin 是以标准的 SQL 作为对外服务的接口
- 支持超大数据集:Kylin 对于大数据的支撑能力可能是目前所有技术中最为领先的。早在 2015 年 eBay 的生产环境中就能支持百亿记录的秒级查询,之后在移动的应用场景中又有了千亿记录秒级查询的案例
- 亚秒级响应:Kylin 拥有优异的查询相应速度,这点得益于预计算,很多复杂的计算,比如连接、聚合,在离线的预计算过程中就已经完成,这大大降低了查询时刻所需的计算量,提高了响应速度
- 可伸缩性和高吞吐率:单节点 Kylin 可实现每秒 70 个查询,还可以结合 Zookeeper分布式协调服务搭建 Kylin 集群,速度更快
- BI 工具集成,Kylin 可以与现有的 BI 工具集成,具体包括如下内容
- ODBC:与 Tableau、Excel、PowerBI 等工具集成
- JDBC:与 Saiku、BIRT 等 Java 工具集成
- RestAPI:与 JavaScript、Web 网页集成
Kylin 开发团队还贡献了 **Zepplin **的插件,也可以使用 Zepplin 来访问 Kylin 服务
1.4 Kylin4.0 升级
Apache Kylin4.0 是 Apache Kylin3.x 之后一次重大的版本更新,它采用了全新的 Spark构建引擎和Parquet 作为存储,同时使用 Spark 作为查询引擎。首先介绍一下 Apache Kylin 4.0 的主要优势,Apache Kylin 4 是完全基于 Spark 去做构建和查询的,能够充分地利用 Spark 的并行化、向量化和全局动态代码生成等技术,去提高大数据场景下查询的效率。
- 数据存储
Apache Kylin 3.0 是使用 Hbase 作为存储结构的,因此我们可以称为是 Kylin on Hbase。而 Apache Kylin 4.0 完全砍掉了 Hbase,底层使用 Parquet 存储文件,因此可以称为 Kylin onParquet。首先来看一下,Kylin on HBase 和 Kylin on Parquet 的对比。Kylin on HBase 的 Cuboid的数据是存放在 HBase 的表里,一个 Segment 对应了一张 HBase 表,查询下压的工作由HBase 协理器处理,因为 HBase 不是真正的列存并且对 OLAP 而言吞吐量不高。Kylin 4将 HBase 替换为 Parquet,也就是把所有的数据按照文件存储,每个 Segment 会存在一个对应的 HDFS 的目录,所有的查询、构建都是直接通过读写文件的方式,不用再经过 HBase。虽然对于小查询的性能会有一定损失,但对于复杂查询带来的提升是更可观的、更值得的。
- 构建引擎
Kylin Cube 的构建引擎,在 Kylin3.0 中,一般都会使用 MR 作为 Cube 构建引擎去逐层构建 Cube,速度较慢。而在 Kylin4.0 中,将构建引擎换成了特定优化的 Spark 引擎,步骤也减少为了两大步,第一步进行资源探测,收集构建 Cube 所需要的元数据信息。第二步使用 Spark 引擎去计算和构建,有效的提升了 Cube 构建速度
- 查询引擎
Kylin3.0 的查询完全依托于 Calcite 引擎和 HBase 的协处理器,这就导致当数据从HBase 读取后,如果想做聚合、排序等,就会局限于 QueryServer 单点的瓶颈,而 Kylin4 则转换为基于 Spark SQL 的 DataFrame 作为查询引擎,得益于 Spark 的分布式查询机制,Kylin4.0 的查询速度也有了不少的改善
2、Kylin 环境搭建
2.1 简介
安装 Kylin 前需先部署好 Hadoop、Hive、Zookeeper、Spark,并且需要在/etc/profile 中配置以下环境变量 HADOOP_HOME,HIVE_HOME,ZOOKEEPER_HOME,SPARK_HOME
记得 source 使其生效。
注意:目前集群中 hadoop3.1.3 和 hive3.1.2 是可以满足 Kylin4.0 安装和使用的,但是经测试 Spark3.0.0 不能满足 Kylin4.0 对 Spark3 最低版本的要求,因此我们需要先升级 Spark 的版本为 3.1.1
2.2 Spark 安装和部署
# 下载新版本
wget https://archive.apache.org/dist/spark/spark-3.1.1/spark-3.1.1-bin-hadoop3.2.tgz
# 解压 spark-3.1.1-bin-hadoop3.2.tgz 到/opt/module
tar -zxvf spark-3.1.1-bin-hadoop3.2.tgz -C /opt/module/
mv /opt/module/spark-3.1.1-bin-hadoop3.2/ /opt/module/spark-3.1.1
# 设置 SPARK_HOME,然后 source 使其生效
sudo vim /etc/profile.d/my_env.sh
#SPARK_HOME
export SPARK_HOME=/opt/module/spark-3.1.1
export PATH=$PATH:$SPARK_HOME/bin
# 刷一下
source /etc/profile
# 修改配置文件 spark_env.sh,让 spark 程序能够正常进入 yarn 集群
cd conf/
mv spark-env.sh.template spark-env.sh
vim spark-env.sh
# 添加以下
YARN_CONF_DIR=/opt/module/hadoop-3.1.3/etc/hadoop
# 拷贝 MySQL 连接驱动到 spark 的 jars 目录下,让 Spark 能够正常连接 MySQL
2.3 Kylin 安装和部署
wget https://dlcdn.apache.org/kylin/apache-kylin-4.0.3/apache-kylin-4.0.3-bin-spark3.tar.gz --no-check-certificate
# 解压 apache-kylin-4.0.3-bin-spark3.tar.gz 到/opt/module
tar -zxvf apache-kylin-4.0.3-bin-spark3.tar.gz -C /opt/module/
mv /opt/module/apache-kylin-4.0.3-bin-spark3/ /opt/module/kylin-4.0.3/
# 将 mysql 连接驱动拷贝一份到 Kylin 的 ext 目录下,方便 Kylin 存储元数据
mkdir ext
cp /opt/software/mysql-connector-java-5.1.37.jar /opt/module/kylin-4.0.3/ext/
# 修改 Kylin 配置文件 kylin.properties,根据实际情况修改以下参数
cd /opt/module/kylin-4.0.3/conf/
vim kylin.properties
#### METADATA | ENV ###
# 元数据存储,用的 mysql
kylin.metadata.url=kylin_metadata@jdbc,url=jdbc:mysql://hadoop102:3306/kylin,username=root,password=123456,maxActive=10,maxIdle=10
# hdfs 工作空间
kylin.env.hdfs-working-dir=/kylin
# kylin 在 zk 的工作目录
kylin.env.zookeeper-base-path=/kylin
# 不用 kylin 自带的 zk
kylin.env.zookeeper-is-local=false
# 外部 zk 连接字符串
kylin.env.zookeeper-connect-string=hadoop102:2181,hadoop103:2181,hadoop104:2181
#### SPARK BUILD ENGINE CONFIGS ###
# hadoop conf 目录位置
kylin.env.hadoop-conf-dir=/opt/module/hadoop-3.1.3/etc/hadoop
# 开启planner
kylin.cube.cubeplanner.enabled=true
2.4 Kylin 启动环境准备
Kylin4.0 使用 Spark 作为计算引擎和查询引擎,因此对 spark 任务运行的 yarn 容器内存有所要求,要求 yarn 容器内存不能低于 4G,因此需要将 Yarn 容器内存调为 8G,否则 kylin启动会报错。
注意:yarn 容器内存都调为了 8G,所以三台虚拟机内存一定要大于 8G,否则 Kylin 运行会报错,此处建议学者将三台虚拟机内存设置为 12G,8G,8G。vim /opt/module/hadoop-3.1.3/etc/hadoop/yarn-site.xml
<!-- yarn 容器允许分配的最大最小内存 -->
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>512</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>8192</value>
</property>
<!-- yarn 容器允许管理的物理内存大小 -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>8192</value>
</property>
<!-- 关闭 yarn 对物理内存和虚拟内存的限制检查 -->
<property>
<name>yarn.nodemanager.pmem-check-enabled</name>
<value>false</value>
</property>
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
最后记得分发三台集群,然后就是增加 ApplicationMaster 资源比例
容量调度器对每个资源队列中同时运行的 Application Master 占用的资源进行了限制,该限制通过 yarn.scheduler.capacity.maximum-am-resource-percent
参数实现,其默认值是 0.1,表示每个资源队列上 Application Master 最多可使用的资源为该队列总资源的 10%,目的是防止大部分资源都被 Application Master 占用,而导致 Map/Reduce Task 无法执行。生产环境该参数可使用默认值。但学习环境,集群资源总数很少,如果只分配 10%的资源给 Application Master,则可能出现,同一队列在同一时刻只能运行一个 Job 的情况,因为一个 Application Master 使用的资源就可能已经达到 10%的上限了。故此处可将该值适当调大。因为 Kylin4.0 的查询会生成一个在后台长期运行的 Sparder 任务,占用 Default 队列,因此一定要调大此参数,否则 Kylin4.0 无法正常使用。
在 hadoop102 的/opt/module/hadoop-3.1.3/etc/hadoop/capacity-scheduler.xml
文件中修改如下参数值,然后分发重启yarn
<property>
<name>yarn.scheduler.capacity.maximum-am-resource-percent</name>
<value>0.8</value>
</property>
最后在 MySQL 里手动创建 kylin 数据库,方便 Kylin 存储元数据
mysql -uroot -p123456
create database kylin;
show databases;
# 启动zk和hadoop
zk.sh start
myhadoop.sh start
2.5 Kylin 启动和关闭
# 可以先检查一下
check-env.sh
# 启动
bin/kylin.sh start
# 停止
bin/kylin.sh stop
# 进程名字为Bootstrap
# 在/opt/module/kylin-4.0.3/logs/kylin.log 查看启动日志
# 在 http://hadoop102:7070/kylin 查看 Web 页面
# 可以使用默认用户登录,用户名为:ADMIN,密码为:KYLIN
注意:第一次启动 Kylin,Web 页面会报 404 错误,查看 kylin 后台启动日志,发现报错没有这个类。分析原因应该是 Kylin4.0 和 Hadoop 或者 Hive 版本不兼容所致,因此需要手动补充两个 Commons 的 jar 包。
cp commons-configuration-1.3.jar /opt/module/kylin-4.0.3/tomcat/webapps/kylin/WEB-INF/lib/
cp commons-collections-3.2.2.jar /opt/module/kylin-4.0.3/tomcat/webapps/kylin/WEB-INF/lib/
ll /opt/module/kylin-4.0.3/tomcat/webapps/kylin/WEB-INF/lib/ | grep commons-co
# 然后关闭 kylin,重新启动即可
3、快速入门
3.1 数据准备
# dept.txt
10 ACCOUNTING 1700
20 RESEARCH 1800
30 SALES 1900
40 OPERATIONS 1700
# emp.txt
7369 SMITH CLERK 7902 1980-12-17 800.00 20
7499 ALLEN SALESMAN 7698 1981-2-20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981-2-22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981-4-2 2975.00 20
7654 MARTIN SALESMAN 7698 1981-9-28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981-5-1 2850.00 30
7782 CLARK MANAGER 7839 1981-6-9 2450.00 10
7788 SCOTT ANALYST 7566 1987-4-19 3000.00 20
7839 KING PRESIDENT 1981-11-17 5000.00 10
7844 TURNER SALESMAN 7698 1981-9-8 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987-5-23 1100.00 20
7900 JAMES CLERK 7698 1981-12-3 950.00 30
7902 FORD ANALYST 7566 1981-12-3 3000.00 20
7934 MILLER CLERK 7782 1982-1-23 1300.00 10
然后建表和导入
# 进入交互界面
hive
# 可能会报很多info信息,设置一下log4j即可
create database kylin_test
use kylin_test
# 创建部门表
create external table if not exists dept(
deptno int,
dname string,
loc int)
row format delimited fields terminated by '\t';
# 创建员工表
create external table if not exists emp(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int)
row format delimited fields terminated by '\t';
show tables;
# 向外部表中导入数据,也可以直接从hdfs导入
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table dept;
hive (default)> load data local inpath '/opt/module/datas/emp.txt' into table emp;
# 可以查询一下
select * from dept;
3.2 Kylin项目创建入门
登陆系统,首先点击+号创建项目,选择好刚创建好的项目;第二步选择数据源,点击model下的Data Source,选择第二个按钮(这里会自动通过spark任务查询,所以yarn内存要大,否则跑不起来),同步要作为数据源的表,这里选择上面创建的两张表
创建 Model
回到 Models 页面,点击 New 按钮后点击 New Model,填写 Model 名称及描述后 Next,选择事实表(这里选择emp作为事实表);添加维度表,点击Add Lookup Table,选择添加的维度表及 join 字段,然后下一步
选择维度信息,下一步选择度量信息sal,最后添加分区信息及过滤条件之后"Save"(这里不填,使用默认)
创建 Cube
点击 New 按钮然后选择 New Cube,选择 Model 及填写 Cube Name;添加真正的维度字段(将来会影响 Cuboid 的个数,并且只能从 model 维度字段里面选择)
然后下一步,点击add dimensions
下一步添加真正度量值字段(将来预计算的字段值,只能从 model 度量值里面选择),这里我选择了sum求和sal薪水字段,后续高级设置都默认。构建完成后,点击cube,可以查看构建的sql,然后点击build构建
3.3 Hive 和 Kylin 性能对比
# 需求:根据部门名称[dname]统计员工薪资总数[sum(sal)]
select dname,sum(sal) from emp e join dept d on e.deptno = d.deptno group by dname;
# 进入kylin的Insight 页面,在 New Query 中输入查询语句并 Submit,亚秒级
# 进入hive查询,需要启动spark等,速度很慢
3.4 Kylin 使用注意事项
-
只能按照构建 Model 的连接条件来写 SQL
因为在创建 Model 的时候,我们对员工表和部门表选用的是 Inner Join 内连接,因此我们在使用 Kylin 查询的时候,也只能用 join 内连接,其他连接会报错;并且还有一个要求就是顺序必须是事实表在前,维度表在后,否则报错
-
只能按照构建 Cube 时选择的维度字段分组统计
我们在构建 Cube 时,选择了四个维度字段 JOB,MGR,DEPTNO,DNAME,所以我们在使用 Kylin 查询的时候,只能按照这四个为的字段进行 Group By 分组统计,使用其他字段,一定会报错
-
只能统计构建 Cube 时选择的度量值字段
我们构建 Cube 时,只添加了一个 SUM(SAL)的度量值,然后加上默认的 COUNT(*),一共有两个度量值,因此我们只可以利用 Kylin 求这两个度量值,求其他报错。
3.5 Kylin 每日自动构建 Cube
https://cwiki.apache.org/confluence/display/KYLIN/Access+and+Authentication+API
Kylin 提供了 Restful API,因次我们可以将构建 cube 的命令写到脚本中,将脚本交给azkaban 或者 oozie 这样的调度工具,以实现定时调度的功能。kylin_cube_build.sh
脚本如下:
#!/bin/bash
#从第 1 个参数获取 cube_name
cube_name=$1
#从第 2 个参数获取构建 cube 时间
if [ -n "$2" ]
then
do_date=$2
else
do_date=`date -d '-1 day' +%F`
fi
#获取执行时间的 00:00:00 时间戳(0 时区)
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
注:我们没有修改 kylin 的时区,因此 kylin 内部只识别 0 时区的时间,0 时区的 0 点是东 8 区的早上 8 点,因此我们在脚本里要写$do_date 08:00:00 来弥补时差问题
3.6 Kylin 设置查询下压
对于没有 cube 能查得结果的 sql,Kylin4.0 支持将这类查询下压至 SparkSql 去查询Hive 源数据
# 设置参数开启
vim /opt/module/kylin-4.0.3/conf/kylin.properties
# 添加如下内容或者打开注释
kylin.query.pushdown.runner-class-name=org.apache.kylin.query.pushdown.PushDownRunnerSparkImpl
# 页面刷新配置或者重启
# 刷新页面在可视化中的System-》Reload Config
# 执行没有 cube 对应的查询,之前会报错,现在可以直接使用spark进行查询,去spark界面也可以查询到和之前查询时不一样的
# System-》sparder
4、Kylin4.0 查询引擎
4.1 查询引擎 Sparder
Sparder(SparderContext)是由 Spark application 后端实现的新型分布式查询引擎,它是作为一个** Long-running 的 Spark application 存在的**。Sparder 会根据 kylin.query.spark-conf
开头的配置项中配置的 Spark 参数来获取 Yarn 资源,如果配置的资源参数过大,可能会影响构建任务甚至无法成功启动 Sparder,如果 Sparder 没有成功启动,则所有查询任务都会失败,因此请在 Kylin 的 WebUI 中检查 Sparder 状态,不过默认情况下,用于查询的 spark 参数会设置的比较小,在生产环境中,大家可以适当把这些参数调大一些,以提升查询性能。
kylin.query.auto-sparder-context-enabled-enabled
参数用于控制是否在启动 kylin 的同时启动 Sparder,默认值为 false,即默认情况下会在执行第一条 SQL 的时候才启动 Sparder,因此 Kylin 的第一条 SQL 查询速度一般比较慢,因为包含了 Sparder 任务的启动时间
4.2 HDFS 存储目录
根目录:/kylin/kylin_metadata
子目录:
- 临时文件存储目录:
/project_name/job_tmp
- Cuboid 文件存储目录:
/project_name/parquet/cube_name/segment_name_XXX
- 维度表快照存储目录:
/project_name /table_snapshot
- Spark 运行日志目录:
/project_name/spark_logs
4.3 Kylin4.0 查询参数汇总
Kylin 查询参数全部以 kylin.query.spark-conf
开头,默认情况下,用于查询的 spark 参数会设置的比较小,在生产环境中,大家可以适当把这些参数调大一些,以提升查询性能
####spark 运行模式####
#kylin.query.spark-conf.spark.master=yarn
####spark driver 核心数####
#kylin.query.spark-conf.spark.driver.cores=1
####spark driver 运行内存####
#kylin.query.spark-conf.spark.driver.memory=4G
####spark driver 运行堆外内存####
#kylin.query.spark-conf.spark.driver.memoryOverhead=1G
####spark executor 核心数####
#kylin.query.spark-conf.spark.executor.cores=1
####spark executor 个数####
#kylin.query.spark-conf.spark.executor.instances=1
####spark executor 运行内存####
#kylin.query.spark-conf.spark.executor.memory=4G
####spark executor 运行堆外内存####
#kylin.query.spark-conf.spark.executor.memoryOverhead=1G
5、Cube优化
5.1 使用衍生维度(derived dimension)
衍生维度用于在有效维度内将维度表上的非主键维度排除掉,并使用维度表的主键(其实是事实表上相应的外键)来替代它们。Kylin 会在底层记录维度表主键与维度表其他维度之间的映射关系,以便在查询时能够动态地将维度表的主键“翻译”成这些非主键维度,并进行实时聚合(在构建cube时,选择维度时,勾选deliver即是维度表,此时这个表的维度数降为1,总构建数2^n-1,n为最新的维度数)
虽然衍生维度具有非常大的吸引力,但这也并不是说所有维度表上的维度都得变成衍生维度,如果从维度表主键到某个维度表维度所需要的聚合工作量非常大,则不建议使用衍生维度
5.2 使用聚合组(Aggregation group)
聚合组(Aggregation Group)是一种强大的剪枝工具。聚合组假设一个 Cube 的所有维度均可以根据业务需求划分成若干组(当然也可以是一个组),由于同一个组内的维度更可能同时被同一个查询用到,因此会表现出更加紧密的内在关联。每个分组的维度集合均是Cube 所有维度的一个子集,不同的分组各自拥有一套维度集合,它们可能与其他分组有相同的维度,也可能没有相同的维度。每个分组各自独立地根据自身的规则贡献出一批需要被物化的 Cuboid,所有分组贡献的 Cuboid 的并集就成为了当前 Cube 中所有需要物化的 Cuboid的集合。不同的分组有可能会贡献出相同的 Cuboid,构建引擎会察觉到这点,并且保证每一个 Cuboid 无论在多少个分组中出现,它都只会被物化一次。
-
强制维度(Mandatory)
如果一个维度被定义为强制维度,那么这个分组产生的所有 Cuboid 中每一个 Cuboid 都会包含该维度。每个分组中都可以有 0 个、1 个或多个强制维度。如果根据这个分组的业务逻辑,则相关的查询一定会在过滤条件或分组条件中,因此可以在该分组中把该维度设置为强制维度。(强制维度自己也不能单独出现)。
-
层级维度(Hierarchy)
每个层级包含两个或更多个维度。假设一个层级中包含D1,D2…Dn 这 n 个维度,那么在该分组产生的任何 Cuboid 中, 这 n 个维度只会以(),(D1),(D1,D2)…(D1,D2…Dn)这 n+1 种形式中的一种出现。每个分组中可以有 0个、1 个或多个层级,不同的层级之间不应当有共享的维度。如果根据这个分组的业务逻辑,则多个维度直接存在层级关系,因此可以在该分组中把这些维度设置为层级维度
-
联合维度(Joint)
每个联合中包含两个或更多个维度,如果某些列形成一个联合,那么在该分组产生的任何 Cuboid 中,这些联合维度要么一起出现,要么都不出现。每个分组中可以有 0 个或多个联合,但是不同的联合之间不应当有共享的维度(否则它们可以合并成一个联合)。如果根据这个分组的业务逻辑,多个维度在查询中总是同时出现,则可以在该分组中把这些维度设置为联合维度。
这些操作可以在 Cube Designer 的 Advanced Setting 中的 Aggregation Groups 区域完成,里面包括了三种维度,可以按照自己需求选择
有时候我们的 Cube 中有一些基数非常大的维度,如果不做特殊处理,它就会和其他的维度进行各种组合,从而产生一大堆包含它的 Cuboid。包含高基数维度的 Cuboid在行数和体积上往往非常庞大,这会导致整个 Cube 的膨胀率变大。如果根据业务需求知道这个高基数的维度只会与若干个维度(而不是所有维度)同时被查询到,那么就可以通过聚合组对这个高基数维度做一定的“隔离”。我们把这个高基数的维度放入一个单独的聚合组,再把所有可能会与这个高基数维度一起被查询到的其他维度也放进来。这样,这个高基数的维度就被“隔离”在一个聚合组中了,所有不会与它一起被查询到的维度都没有和它一起出现在任何一个分组中,因此也就不会有多余的 Cuboid 产生。这点也大大减少了包含该高基数维度的 Cuboid 的数量,可以有效地控制 Cube 的膨胀率。
5.3 Cube 构建参数调优
在 Kylin 4 中,Cube 构建作业中有两个步骤,第一步检测构建为 Cube 数据的源文件,第二步是构建快照表(如果需要),生成全局字典(如果需要)并将 Cube 数据构建为 Parquet文件。在第二步中,所有计算都是具有相对较重的负载的操作,因此除了使用衍生维度和聚合组来减少 Cube 的数量,使用正确的 Spark 资源和配置来构建 Cube 也非常重要
使用适当的 Spark 资源和配置来构建 Cube
Kylin 构建参数全部以 kylin.engine.spark-conf 开头,以下表格中的参数省略开头
参数 | 说明 |
---|---|
spark.executor.instances | Spark 应用程序的 Executor 数量 |
spark.executor.cores | 每个 Executor 使用的核心数,Executor 数量乘以Executor 使用的核心数就是 Spark 程序运行的最大并行度 |
spark.executor.memory | 每个 Executor 使用的内存 |
spark.executor.memoryOverhead | 每个 Executor 使用的堆外内存 |
spark.sql.files.maxPartitionBytes | 读取文件时要打包到单个分区中的最大字节数,默认值为 128M。如果源表(Hive source)中有许多小文件,spark 会自动将许多小文件打包到单个分区中,以避免执行太多的小任务 |
spark.sql.shuffle.partitions | 配置为联接 Join 或聚合 Shuffle 时要使用的分区数,默认值为 200。较大的值需要更多的 CPU 资源,而较小的值需要更多的内存资源 |
Kylin 根据 Cube 情况自动设置 Spark 参数
Kylin 4 将使用以下分配规则来自动设置 Spark 资源和配置,所有 Spark 资源和配置都是根据源文件中最大文件的大小以及 Cube 是否具有准确的去重计数度量来设置的,这就是为什么我们需要在第一步中检测要构建多少个源文件的原因
- Executor 内存规则
如 果 ${ 最 大 文 件 大 小 }>=100G and ${ 存 在 准 确 去 重 度 量 值 }, 设 置spark.executor.memory
为 20G;
如果{最大文件大小}>=100G or (如果${最大文件大小}>=10G and ${存在准确去重度量值}), 设置spark.executor.memory
为 16G;
如果{最大文件大小}>=10G or (如果${最大文件大小}>=1G and ${存在准确去重度量值}), 设置spark.executor.memory
为 10G;
如果{最大文件大小}>=1G or ${存在准确去重度量值}, 设置spark.executor.memory
为 4G;
否则设置spark.executor.memory
为 1G
- Executor 核心数规则
如果{最大文件大小}>=10G or (如果${最大文件大小}>=1G and ${存在准确去重度量值}), 设置spark.executor.cores
为5;否则设置spark.executor.cores
为 1
- Executor 堆外内存规则
如 果 ${ 最 大 文 件 大 小 }>=100G and ${ 存 在 准 确 去 重 度 量 值 }, 设 置spark.executor.memoryOverhead
为 6G;所以这种情况下,每个 Executor 的内存为 20G + 6G= 26G;
如果{最大文件大小}>=100G or (如果${最大文件大小}>=10G and ${存在准确去重度量值}), 设置spark.executor.memoryOverhead
为 4G;
如果{最大文件大小}>=10G or (如果${最大文件大小}>=1G and ${存在准确去重度量值}), 设置spark.executor.memoryOverhead
为 2G;
如果{最大文件大小}>=1G or ${存在准确去重度量值}, 设置spark.executor.memoryOverhead
为 1G;
否则设置spark.executor.memoryOverhead
为 1G
- Executor 实例数量规则
①读取参数’kylin.engine.base-executor-instance’的值作为基本 Executor 数量,默认值为 5
② 根 据 Cuboid 个 数 来 计 算 所 需 的 Executor 个 数 , 配 置 文 件 中 读 取 参 数’kylin.engine.executor-instance-strategy’的值,默认为’100,2,500,3,1000,4’,即Cuboid 个数为 0-100 时,因数为 1;100-500 时,因数为 2;500-1000 时,因数为 3;1000 以上时,因数为 4。然后用这个因数乘以第一步的基本 Executor 数量就是 Executor 的预估总数量
③从 Yarn 资源池中的得到可用的总核心数和总内存数,然后用总核心数和总内存数除以 kylin 任务所需的核心数和内存数,两者求个最小值,就是 Executor 的可用总量
④最后在 Executor 的预估总数量和 Executor 的可用总数量之间取最小值作为Executor的实际最终总数量
- Shuffle 分区数量规则
设置spark.sql.shuffle.partitions
为max(2, ${最大文件大小 MB} / 32)。在应用上述所有分配规则后,可以在"kylin.log"文件中找到一些日志消息
根据实际情况手动设置 Spark 参数
根据 Kylin 自动调整的配置值,如果仍存在一些 Cube 构建性能问题,可以适当更改这些配置的值以进行尝试
如果您从 spark ui 观察到某些任务中存在严重的 GC 现象,或者发现大量 executor丢失或获取失败错误,您可以更改这两个配置的值,以增加每个 executor 的内存
- spark.executor.memory=
- spark.executor.memoryOverhead=
一般调整策略是将参数的值调整为 2 倍。如果问题解决了,您可以适当地调整以避免浪费资源。在增加每个 Executor 的内存后,如果仍有严重的内存问题,可以考虑调整spark.executor.cores
为 1,此调整可以使单个任务是每个 Executor 的独家任务,并且执行效率相对较低,但它可以通过这种方式来避免构建失败
如果您从 spark ui 观察到,有大量任务需要为多轮计划(每轮都用掉了所有内核),您可以更改这两个配置的值,以增加 spark 应用程序的内核数
- spark.executor.cores=
- spark.executor.instances=
如果有一些 Executor 丢失或获取数据错误,并且仅仅因为 Shuffle 期间的减速器数量太小,或者数据倾斜,可以尝试增加spark.sql.shuffle.partitions
的值
- spark.sql.shuffle.partitions=
全局字典构建性能调优
全局字典介绍
https://cwiki.apache.org/confluence/display/KYLIN/Global+Dictionary+on+Spark
在 OLAP 数据分析领域,根据去重结果的要求分为近似去重和精确去重,而精确去重是一种非常常见的要求。Kylin 使用预计算技术来加速大数据分析。在 Cube 的增量构建过程中,为了避免由于对不同时间段分别构造字典而导致最终去重结果出现错误,一个 Cube 中的所有 segments 将使用同一个字典,即全局字典,原理如下
- 每个构建任务都将生成一个新的全局字典
- 每个新的构建任务的字典会根据版本号保存,旧的全局字典会逐渐删除
- 一个全局字典包含一个元数据文件和多个字典文件,每个字典文件称为一个 bucket
- 每个 bucket 被划分为两个映射(Map<Object, Long>),并将这两个映射组合成一个完整的映射关系
调优参数
如果 cube 定义了精确去重(即 count(distinct)语法)的度量值,Kylin4.0 将基于 Spark 为这些度量值分布式地构建全局字段的值(之前版本是单点构建)。这部分的优化主要是调整一个参数
- kylin.dictionary.globalV2-threshold-bucket-size (默认值 500000)
如果 CPU 资源充足,减少此配置的值可以减少单个分区中的数据量,从而加快构建全局字典
使用全局字典
在 已 有 的 Model 中 , 创 建 一 个 新 的 Cube 用 于 测 试 全 局 字 典 , 在Measures界面设 置 度 量 为COUNT_DISTINCT,返回类型选择 Precisely。如果构建失败,可能是 yarn 资源限制,构建时单个容器申请的 cpu 核数超过 yarn 单个容器默认最大 4 核(4核跑不起来),修改 hadoop 的 yarn-site.xml
,分发配置文件,重启 yarn,然后就可以在hdfs上查看dict文件了
<!-- 容器允许分配的最大 cpu 核数-->
<property>
<name>yarn.scheduler.maximum-allocation-vcores</name>
<value>8</value>
</property>
快照表构建性能调优
Snapshot Table - 快照表:每一张快照表对应一个 Hive 维度表,为了实时记录 Hive 维度表的数据变化,Kylin 的 cube 每次构建都会对 hive 维度表创建一个新的快照,以下是快照表的调优参数。构建 Snapshot table 时,主要调整 2 个参数来调优
参数名 | 默认值 | 说明 |
---|---|---|
kylin.snapshot.parallel-build-enabled | true | 使用并行构建,保持开启 |
kylin.snapshot.shard-size-mb | 128MB | 如果 CPU 资源充足,可以减少值来增加并行度,建议并行度在 Spark 应用CPU 核数的 3 倍以内。并行度=原表数据量/该参数 |
6、查询性能优化
在 Kylin4.0 中,查询引擎(SparderContext)也使用 spark 作为计算引擎,它是真正的分布式查询引擎,特别是在复杂查询方面,性能会优于 Calcite。然而,仍然有许多关键性能点需要优化。除了上面提到的设置适当的计算资源之外,它还包括减少小的或不均匀的文件,设置适当的分区,以及尽可能多地修剪 parquet 文件。Kylin4.0 和 Spark 提供了一些优化策略来提高查询性能
6.1 使用排序列快速读取 parquet 文件
创建 cube 时,可以指定维度列的排序,当保存 cube 数据时,每个 cuboid 的第一个维度列将用于执行排序操作。其目的是在使用排序列进行查询时,通过 parquet 文件的最小最大索引尽可能地过滤不需要的数据。在cube里的advance setting里,rowkey 的顺序就是排序顺序,页面中可以左键点击 ID 进行拖拽,调整顺序
6.2 使用 shardby 列来裁剪 parquet 文件
Kylin4.0 底层存储使用的是 Parquet 文件,并且 Parquet 文件在存储的时候是会按照某一列进行分片的。这个分片的列在 Kylin 里面,我们称为是 shardBy 列,Kylin 默认按照 shardBy列进行分片,分片能够使查询引擎跳过不必要的文件,提高查询性能。我们在创建 Cube 时可以指定某一列作为 shardBy 列,最好选择高基列(基数高的列),并且会在多个 cuboid 中出现的列作为 shardBy 列。
我们按照时间(月)过滤,生成对应的 Segment,然后按照维度 A 作为shardBy 列进行分片,每个 Segment 里面都会有相应的分片。如果我们在查询的时候按照时间和维度 A 进行过滤,Kylin 就会直接选择对应 Segment 的对应分片,大大的提升的查询效率
查询时,查询引擎可以通过日期分区列过滤出 segment-level 目录,并通过 cuboid 过滤出cuboid-level 目录。但是在 cuboid-level 目录中仍有许多 parquet 文件,可以使用 shard by 列进一步裁剪parquet文件。目前在SQL查询中只支持以下过滤操作来裁剪parquet文件:Equality、In、InSet、IsNull。
操作方式是在构建cube时点击advance setting,在rowKeys选择需要的列,将 shardby 改成 true即可。当构建 cube 数据时,它会根据这个 shard 按列对 parquet 文件进行重分区。如果没有指定一个 shardby 的列,则对所有列进行重分区
6.3 减少小的或不均匀的 parquet 文件
在查询时读取太多小文件或几个太大的文件会导致性能低下,为了避免这个问题,Kylin4.0 在将 cube 数据作为 parquet 文件构建时,会按照一定策略对 parquet 文件进行重分区,以减少小的或不均匀的 parquet 文件
相关配置
参数名 | 默认值 | 说明 |
---|---|---|
kylin.storage.columnar.shard-size-mb | 128MB | 有 shardby 列的 parquet 文件最大大小 |
kylin.storage.columnar.shard-rowcount | 2500000 | 每个 parquet 文件最多包含的行数 |
kylin.storage.columnar.shard-countdistinct-rowcount | 1000000 | 指定 cuboid 的 bitmap 大小 |
kylin.storage.columnar.repartition-threshold-size-mb | 128MB | 每个 parquet 文件的最大大小 |
重分区的检查策略
- 如果这个 cuboid 有 shardBy 的列;
- parquet 文件的平均大小 < 参数
kylin.storage.columnar.repartition-threshold-size-mb
值 ,且 parquet 文件数量大于 1;这种情况是为了避免小文件太多; - parquet 文件的数量 < (parquet 文件的总行数/
kylin.storage.columnar.shard-rowcount
* 0.75),如果这个 cuboid 有精确去重的度量值(即 count(distinct)),使用kylin.storage.columnar.shard-countdistinct-rowcount
来代替kylin.storage.columnar.shard-rowcount
;这种情况是为了避免不均匀的文件;
如果满足上述条件之一,它将进行重分区,分区的数量是这样计算的:
- ${fileLengthRepartitionNum} =Math.ceil(${parquet 文件大小 MB} / ${kylin.storage.columnar.shard-size-mb})
- ${rowCountRepartitionNum} =Math.ceil(${parquet 文件总行数} / ${kylin.storage.columnar.shard-rowcount})
- 分区数量=Math.ceil(( ${fileLengthRepartitionNum} + ${ rowCountRepartitionNum } ) / 2)
合理调整参数的方式
# 查看重分区的信息,可以通过下面命令去 log 中查找
grep "Before repartition, cuboid" logs/kylin.log
# 比如官方案例:可以看到分区数有 809 个
# 增大kylin.storage.columnar.shard-rowcount
# 或 kylin.storage.columnar.shard-countdistinct-rowcount的值,重新构建,查看日志:
# 可以看到:分区数变成了 3 个,构建的时间也从 58 分钟降低到 24 分钟
6.4 将多个小文件读取到同一个分区
当已经构建的 segments中有很多小文件时,可以 修改参数spark.sql.files.maxPartitionBytes
(默认值为 128MB)为合适的值,这样可以让 spark 引擎将一些小文件读取到单个分区中,从而避免需要太多的小任务
如 果 有 足 够 的 资 源 , 可 以 减 少 该参数 的 值 来 增 加 并 行 度 , 但 需 要 同 时 减 少spark.hadoop.parquet.block.size
(默认值为 128MB)的值,因为 parquet 文件的最小分割单元是RowGroup,这个 blocksize 参数表示 parquet 的 RowGroup 的最大大小
6.5 使用堆外内存
Spark 可以直接操作堆外内存,减少不必要的内存开销,减少频繁的 GC,提高处理性能
spark.memory.offHeap.enabled | 设置为 true,使用堆外内存进行 spark shuffle |
---|---|
spark.memory.offHeap.size | 堆外内存的大小 |
7、BI 工具集成
7.1 JDBC
首先引入对应版本依赖
<dependency>
<groupId>org.apache.kylin</groupId>
<artifactId>kylin-jdbc</artifactId>
<version>4.0.3</version>
</dependency>
查询创建
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 dname,sum(sal) from emp e join dept d on e.deptno = d.deptno group by dname");
//执行查询
ResultSet resultSet = ps.executeQuery();
//遍历打印
while (resultSet.next()) {
System.out.println(resultSet.getString(1)+":"+resultSet.getDouble(2));
}
}
7.2 Zepplin
Zeppelin是一个基于Web的notebook,提供交互数据分析和可视化。后台支持接入多种数据处理引擎,如spark,hive等。支持多种语言: Scala(Apache Spark)、Python(Apache Spark)、SparkSQL、 Hive、 Markdown、Shell等
# ================安装与启动======================
# 下载,需要科学
wget https://dlcdn.apache.org/zeppelin/zeppelin-0.10.1/zeppelin-0.10.1-bin-all.tgz
# 解压
tar -zxvf zeppelin-0.10.1-bin-all.tgz -C /opt/module/
cd /opt/module/
mv zeppelin-0.10.1-bin-all/ zeppelin
# 因为可能端口冲突,建议修改
mv conf/zeppelin-site.xml.template conf/zeppelin-site.xml
# 然后里面修改ip为hadoop102以及修改端口为8989,自己选一个不冲突的即可
# 启动,zeppelin.sh是前台启动
bin/zeppelin-daemon.sh start
# 可登录网页查看,web 默认端口号为 8080。 http://hadoop102:8080
# 服务名称为ZeppelinServer
然后配置 Zepplin 支持 Kylin,登陆成功后,点击右上角 anonymous 选择 Interpreter,搜索 Kylin 插件并修改相应的配置(ip域名和项目名字,这里默认是kylin用户名密码)
保存成功后,点击create note,注意要选择kylin引擎,创建成功后,即可享受和jupyter类似的笔记式查询
8、MDX For Kylin
8.1 概述
Mondrian、MDX 相关含义:https://segmentfault.com/a/1190000007782683
MDX for Kylin 是基于 Mondrian 二次开发的、由 Kyligence 贡献的、使用 ApacheKylin 作为数据源的 MDX 查询引擎 。MDX for Kylin 的使用体验比较接近 Microsoft SSAS,可以集成多种数据分析工具,包括 Microsoft Excel、Tableau 等,可以为大数据分析场景下提供更极致的体验
MDX for Kylin 是在决策支持和业务分析中使用的分析数据引擎。MDX for Kylin 助力消除数据孤岛,统一数据口径,提高数据业务转化效率,提升运营决策能力。
MDX for Kylin 相对其它开源 MDX 查询引擎,具有以下优势:
- 更好支持 BI (Excel/Tableau/Power BI 等) 产品,适配 XMLA 协议;
- 针对 BI 的 MDX Query 进行了特定优化重写;
- 适配 Kylin 查询,通过 Kylin 的预计算能力加速 MDX 查询;
- 通过简洁易懂的操作界面,提供了统一的指标定义和管理能力。
8.2 mdx的安装与使用
MDX for Kylin 需要对接一个 Kylin 实例或集群,现在 MDX for Kylin 能对接 Kylin版本为 4.0.2 及以上。如果使用的kylin是小于4.0.2的需要替换一个jar包
# 上传 kylin-server-base-4.0.1.jar 包,覆盖原有 jar 包
# 可以参考https://github.com/Kyligence/mdx-kylin/issues/1#issue-1174836123
cp /opt/software/kylin-server-base-4.0.1.jar /opt/module/kylin-4.0.1/tomcat/webapps/kylin/WEB-INF/lib
# 重启 kylin
bin/kylin.sh restart
# 如果版本正常就不需要管
# 同时需要的依赖环境
# JAVA 环境:JDK8 或以上,推荐的元数据库驱动 jar 版本,mysql-connector-java-8.0.16, 请下载到 <MDX for Kylin 安装目录>/semantic-mdx/lib/ 下或者替换所需的 mysql connector 版本到该路径下
# 安装mdx前需要首先创建元数据库
# MySQL 创建数据库
create database mdx default character set utf8mb4 collate utf8mb4_unicode_ci;
# 注意:将 character_set_database 设定为 utf8mb4 或 utf8, 将 collation_server 设定为utf8mb4_unicode_ci 或 utf8_unicode_ci
tar -zxvf mdx-for-kylin-1.0.0-beta.tar.gz -C /opt/module
wget https://s3.cn-north-1.amazonaws.com.cn/public.kyligence.io/kylin/tar/mdx-for-kylin-1.0.0-beta.tar.gz
tar -zxvf mdx-for-kylin-1.0.0-beta.tar.gz -C /opt/module
# 加密元数据库访问密码
bin/mdx.sh encrypt '123456'
# 注意:如果输入的密码包含特殊字符, 需要用单引号包裹, 如果密码里面有单引号, 那么可以用双引号包裹。
# 记录加密后的密文:698d2c7907fc9b6dbe7f8a8c4cb0297a
# 修改配置文件,修改 conf 目录下 insight.properties 配置
vim conf/insight.properties
# 修改一下参数
insight.kylin.host=hadoop102
insight.kylin.port=7070
insight.database.type=mysql
insight.database.ip=hadoop102
insight.database.port=3306
insight.database.name=mdx
insight.database.username=root
insight.database.password=698d2c7907fc9b6dbe7f8a8c4cb0297a
insight.mdx.cluster.nodes=hadoop102:7080
# 注意:password 是前面加密后的密文
# 然后复制jdbc驱动到lib目录
cp /opt/software/mysql-connector-java-5.1.37.jar /opt/module/mdx-for-kylin-1.0.0-beta/semantic-mdx/lib/
# 启动 MDX For Kylin
# 首次启动会需要几分钟的时间来更新元数据
bin/mdx.sh start
# 注意:在首次启动时,由于未并未填写与 Kylin 通信的账户信息,所以同步任务会失败。详情如下图,此时可正常登陆 MDX for Kylin 并填写同步信息,填写后即可正常同步
# 安装成功后,通过 http://hadoop102:7080/login/ 登陆 MDX for Kylin,密码和 Kylin 一样,默认是 ADMIN/KYLIN。
# 然后输入同步的kylin用户名密码,同样是输入 ADMIN/KYLIN
# 停止 MDX for Kylin
bin/mdx.sh stop
8.3 设计数据集
打开 mdx 的 Web UI,创建数据集:http://hadoop102:7080,随便输入数据集名称后下一步,拖拽模型到右侧画布(注意是启动的cube才显示),修改维度和度量(名称、属性,更多修改维度和度量属性的操作),定义翻译,确定保存
8.4 excel分析数据
打开 Excel,设置获取数据
填写参数,名称的格式为:http://{host}:{port}/mdx/xmla/{project}
选择数据库和表,保存文件并完成
然后单元格选择导入数据,选择数据透视图,完成即可分析了
二、Presto
1、Presto简介
1.1 概述
Presto是一个开源的分布式SQL查询引擎,数据量支持GB到PB字节,主要用来处理秒级查询的场景。注意:虽然Presto可以解析SQL,但它不是一个标准的数据库。不是MySQL、Oracle的代替品,也不能用来处理在线事务(OLTP ) 。
1.2 Presto架构
1.3 Presto优缺点
1.4 Presto、Impala性能比较
测试结论:Impala性能稍领先于Presto,但是Presto在数据源支持上非常丰富,包括Hive、图数据库、传统关系型数据库、Redis等
2、Presto安装
2.1 Presto Server安装
各版本下载:https://repo1.maven.org/maven2/com/facebook/presto/presto-server/
# https://prestodb.io/docs/current/installation/deployment.html
cd /opt/software
wget https://repo1.maven.org/maven2/com/facebook/presto/presto-server/0.196/presto-server-0.196.tar.gz
tar -zxvf presto-server-0.196.tar.gz -C /opt/module/
mv presto-server-0.196/ presto
# 进入到/opt/module/presto目录,并创建存储数据文件夹
cd presto
mkdir data
# 存储配置文件文件夹
mkdir etc
# 配置在/opt/module/presto/etc目录下添加jvm.config配置文件
vim etc/jvm.config
# 添加如下内容
-server
-Xmx16G
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+UseGCOverheadLimit
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:+ExitOnOutOfMemoryError
# Presto可以支持多个数据源,在Presto里面叫catalog,这里我们配置支持Hive的数据源,配置一个Hive的catalog
mkdir etc/catalog
vim etc/catalog/hive.properties
# 添加如下内容
connector.name=hive-hadoop2
hive.metastore.uri=thrift://hadoop102:9083
# 将hadoop102上的presto分发到hadoop103、hadoop104
xsync presto
# 分发之后,分别进入hadoop102、hadoop103、hadoop104三台主机的/opt/module/presto/etc的路径。配置node属性,node id每个节点都不一样
[atguigu@hadoop102 etc]$vim node.properties
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-ffffffffffff
node.data-dir=/opt/module/presto/data
[atguigu@hadoop103 etc]$vim node.properties
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-fffffffffffe
node.data-dir=/opt/module/presto/data
[atguigu@hadoop104 etc]$vim node.properties
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-fffffffffffd
node.data-dir=/opt/module/presto/data
# Presto是由一个coordinator节点和多个worker节点组成。在hadoop102上配置成coordinator,在hadoop103、hadoop104上配置为worker
vim etc/config.properties
# 添加内容如下
coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8881
query.max-memory=50GB
discovery-server.enabled=true
discovery.uri=http://hadoop102:8881
# hadoop103、hadoop104上配置worker节点
coordinator=false
http-server.http.port=8881
query.max-memory=50GB
discovery.uri=http://hadoop102:8881
# 在hadoop102的/opt/module/hive目录下,启动Hive Metastore,用atguigu角色
nohup bin/hive --service metastore >/dev/null 2>&1 &
# 分别在hadoop102、hadoop103、hadoop104上启动Presto Server,三台机器依次启动
# 前台启动Presto,控制台显示日志
bin/launcher run
# 后台启动Presto
bin/launcher start
# 日志查看路径/opt/module/presto/data/var/log
2.2 Presto命令行Client安装
# 下载Presto的客户端
wget https://repo1.maven.org/maven2/com/facebook/presto/presto-cli/0.196/presto-cli-0.196-executable.jar
# 修改文件名称
mv presto-cli-0.196-executable.jar prestocli
chmod +x prestocli
# 启动prestocli
./prestocli --server hadoop102:8881 --catalog hive --schema default
# Presto命令行操作
# Presto的命令行操作,相当于Hive命令行操作。每个表必须要加上schema
select * from schema.table limit 100;
# 如果发现因为压缩例如lzo问题无法查询,可以将hadoop的压缩jar包复制到plugins中的特定连接器中
# /opt/module/hadoop-3.1.3/share/hadoop/common/
# 最后重启即可
2.3 Presto可视化Client安装
# 已编译包获取:https://download.csdn.net/download/lemon_TT/87951242
# 自行编译可以参考:https://blog.csdn.net/cz124560/article/details/128316460
# 将yanagishima-18.0.zip上传到hadoop102的/opt/module目录
unzip yanagishima-18.0.zip
cd yanagishima-18.0
# 进入到/opt/module/yanagishima-18.0/conf文件夹,编写yanagishima.properties配置
# 添加如下内容
jetty.port=7080
presto.datasources=atguigu-presto
presto.coordinator.server.atguigu-presto=http://hadoop102:8881
catalog.atguigu-presto=hive
schema.atguigu-presto=default
sql.query.engines=presto
# 在/opt/module/yanagishima-18.0路径下启动yanagishima
nohup bin/yanagishima-start.sh >y.log 2>&1 &
# 启动web页面 http://hadoop102:7080 ,注意不联网可能就是空白的
# 查看表结构
# 这里有个Tree View,可以查看所有表的结构,包括Schema、表、字段等。
# 比如执行select * from hive.dw_weather.tmp_news_click limit 10,这个句子里Hive这个词可以删掉,是上面配置的Catalog
3、Presto优化之数据存储
3.1 合理设置分区
与Hive类似,Presto会根据元数据信息读取分区数据,合理的分区能减少Presto数据读取量,提升查询性能
3.2 使用列式存储
Presto对ORC文件读取做了特定优化,因此在Hive中创建Presto使用的表时,建议采用ORC格式存储。相对于Parquet,Presto对ORC支持更好
3.3 使用压缩
数据压缩可以减少节点间数据传输对IO带宽压力,对于即席查询需要快速解压,建议采用Snappy压缩
4、Presto优化之查询SQL
4.1 只选择使用的字段
由于采用列式存储,选择需要的字段可加快字段的读取、减少数据量。避免采用*读取所有字段
[GOOD]: SELECT time, user, host FROM tbl
[BAD]: SELECT * FROM tbl
4.2 过滤条件必须加上分区字段
对于有分区的表,where语句中优先使用分区字段进行过滤。acct_day是分区字段,visit_time是具体访问时间
[GOOD]: SELECT time, user, host FROM tbl where acct_day=20171101
[BAD]: SELECT * FROM tbl where visit_time=20171101
4.3 Group By语句优化
合理安排Group by语句中字段顺序对性能有一定提升。将Group By语句中字段按照每个字段distinct数据多少进行降序排列
[GOOD]: SELECT GROUP BY uid, gender
[BAD]: SELECT GROUP BY gender, uid
4.4 Order by时使用Limit
Order by需要扫描数据到单个worker节点进行排序,导致单个worker需要大量内存。如果是查询Top N或者Bottom N,使用limit可减少排序计算和内存压力。
[GOOD]: SELECT * FROM tbl ORDER BY time LIMIT 100
[BAD]: SELECT * FROM tbl ORDER BY time
4.5 使用Join语句时将大表放在左边
Presto中join的默认算法是broadcast join,即将join左边的表分割到多个worker,然后将join右边的表数据整个复制一份发送到每个worker进行计算。如果右边的表数据量太大,则可能会报内存溢出错误
[GOOD] SELECT ... FROM large_table l join small_table s on l.id = s.id
[BAD] SELECT ... FROM small_table s join large_table l on l.id = s.id
5、注意事项
5.1 字段名引用
避免和关键字冲突:MySQL对字段加反引号、Presto对字段加双引号分割,当然,如果字段名称不是关键字,可以不加这个双引号。
5.2 时间函数
对于Timestamp,需要进行比较的时候,需要添加Timestamp关键字,而MySQL中对Timestamp可以直接进行比较。
/*MySQL的写法*/
SELECT t FROM a WHERE t > '2017-01-01 00:00:00';
/*Presto中的写法*/
SELECT t FROM a WHERE t > timestamp '2017-01-01 00:00:00';
5.3 不支持INSERT OVERWRITE语法
Presto中不支持insert overwrite语法,只能先delete,然后insert into
5.4 PARQUET格式
Presto目前支持Parquet格式,支持查询,但不支持insert