提升 Hive Query 执行效率 - Hive LLAP
从 Hive 刚推出到现在,得益于社区对它的不断贡献,使得 Hive执行 query 效率显著提升。其中比较有代表性的功能如 Tez (将多个 job整合为一个DAG job)以及 CBO(Cost-based-optimization)。
Hive 在 2.0 版本以后推出了一个新特性名为 LLAP(Live Long And Process),它可以显著提高 hive query的效率。
LLAP提供了一种混合模型,它包含一个长驻进程,用于直接与DataNode 进行IO交互,并紧密地集成在基于DAG的框架中。Caching,pre-fetching,部分query的执行,以及 access control被移动到此进程执行。
大部分Small/short queries被此进程直接处理。而如果是大型任务(如在reduce阶段中的大型shuffle) 则仍被标准的yarn containers 处理。此外,LLAP 还提供了更精细的访问控制。
类似于 DataNode 进程,LLAP 进程也可被其他应用访问,特别是在以文件为中心(file-centric)的关系型数据处理(如 join,多表查询)中。下图展示了 带有LLAP 的执行引擎的一个例子:
可以看到,Tez AM 仍作为 Application Master,处理整个任务调度。Query在初始阶段即被送往 LLAP。在Reduce阶段中,大型的 shuffles 操作在不同的 containers 中执行。多个 queries 与 applications 可以并行地访问 LLAP。
为了满足 caching 以及 JIT 优化,以及减少大部分的启动消耗(startup costs),LLAP 会在每个从节点上启动一个常驻进程。这个进程用于处理 I/O,caching,以及query中部分片段的执行。
LLAP 与集群中执行引擎共同工作,以保留 Hive 原有的性能(如可扩展性能)。LLAP 并不会替代已存在的执行引擎,而是增强它的功能。这里需要注意的几点是:
1. 这些进程是可选的。没有他们,Hive也可以正常工作
2. LLAP 并不是一个执行引擎(如MR or Tez)。一个query 的整个执行过程仍由原有的执行引擎调度与监控。LLAP级别的支持暂时仅对 Tez 可用
3. 取决于query,一个LLAP进程可以提供query的部分结果,或是转交给外部的Hive Task
4. 资源管理仍由 YARN 负责。在YARN container 分配资源后,执行引擎可以决定哪些资源可以被分配给LLAP,或者它可以启动 Apache Tez processors 在一个独立的 YARN container中。
搭建 Hive LLAP
下面介绍一下搭建 LLAP 的流程
1. 安装 Apache Slider
由于Hive LLAP 基于 Apache Slider,所以需要先在主节点上安装 Apache Slider。
Github地址地址:https://github.com/apache/incubator-retired-slider/tree/branches/branch-0.92
下载后使用 maven 编译:mvn clean site:site site:stage package -DskipTests
完成后解压 apache-slider-0.92.0-incubating/slider-assembly/target/slider-0.92.0-incubating-all.tar.gz
文件目录如下:
编辑 conf/slider-env,加入 JAVA_HOME 以及 HADOOP_CONF_DIR 环境变量:
编辑 conf/slider-client.xml,指定集群 zookeeper 地址:
<property>
<name>hadoop.registry.zk.quorum</name>
<value>xxxxxx:2181</value>
</property>
将 bin/ 目录加入 PATH 环境变量,执行 slider 命令,验证是否安装成功:
2.LLAP 配置
hive-site.xml 中添加以下参数:
<property>
<name>hive.zookeeper.quorum</name>
<value>xxxxx:2181</value>
</property>
<property>
<name>hive.execution.mode</name>
<value>llap</value>
</property>
<property>
<name>hive.llap.execution.mode</name>
<value>all</value>
</property>
<property>
<name>hive.llap.daemon.service.hosts</name>
<value>@llap_demo</value>
</property>
<property>
<name>tez.runtime.io.sort.mb</name>
<value>150</value>
</property>
使用以下命令生成 llap 环境包:
hive --service llap --name llap_demo\
--instances 2\
--cache 512m\
--executors 4\
--iothreads 4\
--size 4096m\
--xmx 2048m\
--loglevel INFO\
--args "-XX:+UseG1GC -XX:+ResizeTLAB -XX:+UseNUMA -XX:-ResizePLAB -XX:MaxGCPauseMillis=200"\
--javaHome $JAVA_HOME
--instances指定多少个从节点
--cache 指定每个节点的cache大小
--executors 指定节点executors 数量
--iothread 指定每个实例的 io 线程数
--size 指定每个节点的container内存大小
--xmx 指定container JVM 堆大小
--log-lever 指定日志等级
在执行过程中,需要用到 hbase 相关 jar 包,若报错与此相关,则添加相应依赖到 hive lib,如:
sudo cp -r /usr/lib/hbase/* /usr/lib/hive/lib
执行完成后会生成一个命名为 llap-slider-(%Date) 格式的文件夹,如 llap-slider-19Mar2019,运行文件夹内 run.sh,即可启动 LLAP 常驻进程,如 yarn 界面下:
此时会在从节点上均启动一个 container,一般会启动失败,报错为缺少依赖jar 包。在从节点上启动 container 时,相关 jar 依赖位于 llap-slider-19Mar2019 文件下的 llap-slider-19Mar2019.zip 解压后的 files 下:
若需要添加 jar 包,则需先解压 llap-19Mar2019.tar.gz,然后将 jar 包加入此文件夹,最后再打包还原成原目录结构,例如:
cd llap-slider-19Mar2019
unzip llap-19Mar2019.zip -d unzipped
cd unzipped
cd package
cd files
tar -xvzf llap-19Mar2019.tar.gz
rm -rf llap-19Mar2019.tar.gz
tar -cvzf llap-19Mar2019.tar.gz *
// 添加 jar 包
sudo cp /usr/lib/hadoop/*.jar .
...
rm -rf bin conf config.json lib
cd /home/hadoop/llap-slider-19Mar2019
rm -rf llap-19Mar2019.zip
cd unzipped
zip -r llap-19Mar2019.zip *
cp llap-19Mar2019.zip ../
cd ..
rm -rf unzipped/
启动成功后,可以在 application master 界面理看到:
测试
在 LLAP 成功启动后,下面对 Hive query 效率进行测试。这里我们使用 hortonworks 提供的 hive-testbench。
Github地址为:https://github.com/hortonworks/hive-testbench
下载并编译生成环境后,生成 30 G数据:
./tpcds-setup.sh 30
在 hive shell 中,设置 llap 模式为 none:
hive> set hive.llap.execution.mode=node;
执行提供的示例 sql 语句:
可以看到此任务跑了 131 秒。开启 llap 模式,再次运行:
hive> set hive.llap.execution.mode=all;
可以看到执行仅耗费 50 秒,前文提到 LLAP 会使用cache优化query,所以若是再次执行同一query,会比之前运行更快:
LLAP 可以显著提升 Hive query 执行效率。但由于 LLAP 为常驻进程,会持续占用 yarn 可用资源。若集群并不单独作为 hive 数仓,而是用于各类应用(Spark、Hive 等),则是否在集群使用仍需权衡。