HIVE 跑个 insert into select xxx 为什么 CPU 飙高
HIVE 跑个 insert into select xxx 为什么 CPU 飙高近期做一款数据湖的选型性能比对,发现跑个 Hive 的 insert into select xxx 做入库的性能测试时,想着按理 map 阶段都是从一张表里面读取数据对磁盘 IO 有压力而已,结果发现集群的 cpu 也伴随着比较高,我们来分析分析吧!执行 HIVE SQL 如下:
跑完,发现磁盘 IO 与 CPU 都有一个峰值的高
1. 现象展示
这里磁盘能理解,hadoop hdfs 这里采取了策略,最先开始的表数据激进在机器单机的某块盘上所以起初的 Map 阶段对磁盘压力比较高,但是为什么 CPU 比较高呢?
2. 分析原因
我们看看进程有哪些,哪些进程又占用 CPU 比较高
其中 Tezchild 占 CPU 比较高
Tezchild 是怎么产生的呢,这里是由于我们选的 Hive 的执行引擎为 Tez,那他为什么会比较占内存与 CPU 呢? 这就要从 Tez 执行引擎的原理与概念说起。
3. Tez
3.1 概述
Tez 是 Apache 最新的支持 DAG 作业的开源计算框架,它可以将多个有依赖的作业转换为一个作业从而大幅提升 DAG 作业的性能。Tez 并不直接面向最终用户——事实上它允许开发者为最终用户构建性能更快、扩展性更好的应用程序。
Tez 构建在 YARN 之上,后者是 Hadoop 所使用的新资源管理框架。Tez 产生的主要原因是绕开 MapReduce 所施加的限制。除了必须要编写 Mapper 和 Reducer 的限制之外,强制让所有类型的计算都满足这一范例还有效率低下的问题——例如使用 HDFS 存储多个 MR 作业之间的临时数据,这是一个负载。在 Hive 中,查询需要对不相关的 key 进行多次 shuffle 操作的场景非常普遍,例如 join - grp by - window function - order by。
3.2 Tez 产生背景
MR 性能差,资源消耗大,如:Hive 作业之间的数据不是直接流动的,而是借助 HDFS 作为共享数据存储系统,即一个作业处理好的数据写入 HDFS, 下一个作业再从 HDFS 重新读取数据进行处理,很并行更高效的方式是,第一个作业直接将数据传递给下游作业。MR 默认了 Map 与 Reduce 阶段,map 会对中间结果进行分区,排序,reduce 会进行合并排序,这一过程并不适用于所有场景。引擎级别的 Runtime 优化:MR 执行计划在编译时已经确定,无法动态调整。然而在执行 ETL 和 Ad-hoc 等任务时,根据实际处理表大小,动态调整 join 策略、任务并行度将大大缩短任务执行时间。官方 Tez 与 MR 比对图就能很清楚
总的来说之前 mapReduce 在 map 和 reduce 阶段都会产生 I/O 落盘,但是 Tez 就不要这一步骤了。目前 hive 使用了 Tez(Hive 是一个将用户的 SQL 请求翻译为 MR 任务,最终查询 HDFS 的工具 Tez 采用了 DAG(有向无环图)来组织 MR 任务。核心思想:将 Map 任务和 Reduce 任务进一步拆分,Map 任务拆分为 Input-Processor-Sort-Merge-Output,Reduce 任务拆分为 Input-Shuffer-Sort-Merge-Process-output,Tez 将若干小任务灵活重组,形成一个大的 DAG 作业。Tez 与 oozie 不同:oozie 只能以 MR 任务为整体来管理、组织,本质上仍然是多个 MR 任务的执行,不能解决上面提到的多个任务之间硬盘 IO 冗余的问题。 Tez 只是一个 Client,部署很方便。 目前 Hive 使用了 Tez(Hive 是一个将用户的 SQL 请求翻译为 MR 任务,最终查询 HDFS 的工具)。
3.3 Tez 原理
Tez 包含的组件:有向无环图(DAG)——定义整体任务。一个 DAG 对象对应一个任务。节点(Vertex)——定义用户逻辑以及执行用户逻辑所需的资源和环境。一个节点对应任务中的一个步骤。边(Edge)——定义生产者和消费者节点之间的连接。边需要分配属性,对 Tez 而言这些属性是必须的,有了它们才能在运行时将逻辑图展开为能够在集群上并行执行的物理任务集合。下面是一些这样的属性:数据移动属性,定义了数据如何从一个生产者移动到一个消费者。调度(Scheduling)属性(顺序或者并行),帮助我们定义生产者和消费者任务之间应该在什么时候进行调度。数据源属性(持久的,可靠的或者暂时的),定义任务输出内容的生命周期或者持久性,让我们能够决定何时终止。该模型所有的输入和输出都是可插拔的。为了方便,Tez 使用了一个基于事件的模型,目的是为了让任务和系统之间、组件和组件之间能够通信。事件用于将信息(例如任务失败信息)传递给所需的组件,将输出的数据流(例如生成的数据位置信息)传送给输入,以及在运行时对 DAG 执行计划做出改变等。Tez 还提供了各种开箱即用的输入和输出处理器。这些富有表现力的 API 能够让更高级语言(例如 Hive)的编写者很优雅地将自己的查询转换成 Tez 任务。
TEZ 技术:Application Master Pool 初始化 AM 池。Tez 先将作业提交到 AMPoolServer 服务上。AMPoolServer 服务启动时就申请多个 AM,Tez 提交作业会优先使用缓冲池资源 Container Pool AM 启动时会预先申请多个 Container,并且 Container 是重用
TEZ 实现方法:Tez 对外提供了 6 种可编程组件,分别是:Input:对输入数据源的抽象,它解析输入数据格式,并吐出一个个 Key/valueOutput:对输出数据源的抽象,它将用户程序产生的 Key/value 写入文件系统**Paritioner:**对数据进行分片,类似于 MR 中的 Partitioner**Processor:**对计算的抽象,它从一个 Input 中获取数据,经处理后,通过 Output 输出**Task:**对任务的抽象,每个 Task 由一个 Input、Ouput 和 Processor 组成**Maser :**管理各个 Task 的依赖关系,并按顺依赖关系执行他们
除了以上 6 种组件,Tez 还提供了两种算子,分别是 Sort(排序)和 Shuffle(混洗),为了用户使用方便,它还提供了多种 Input、Output、Task 和 Sort 的实现
DAG:Edge:定义了上下游 Vertex 之间的连接方式。Edge 相关属性:Data movement:定义了 producer 与 consumer 之间数据流动的方式。One-To-One: 第 i 个 producer 产生的数据,发送给第 i 个 consumer。这种上下游关系属于 Spark 的窄依赖。Broadcast: producer 产生的数据路由都下游所有 consumer。这种上下游关系也属于 Spark 的窄依赖。Scatter-Gather: producer 将产生的数据分块,将第 i 块数据发送到第 i 个 consumer。这种上下游关系属于 Spark 的宽依赖。
Input: 接收上游 Output 事件,获取上游数据位置;从 physical Edge 中获取实际数据;解析实际数据,为 Processor 提供统一的逻辑试图;Processor: 利用 Input 获取实际数据,执行用户逻辑,最后输出;Output: 将 Processor 提供的数据,进行分区;向下游 Input 发送事件;Tez 的事件驱动机制: Tez 中各个组件通过不同类型的 Event 进行通信。数据传输:Output 通过 ShuffleEvent 传递上游数据位置,AM 负责将 Event 路由到相应 Input 中。容错:Input 当无法获取到上游数据时,会通知框架重新调度上游任务,这也意味着任务成功完成后,仍然会被重新调度。runtime 执行计划优化:根据上游 Map Stage 产生的数据大小,动态 reducer 并行度。Output 产生的事件路由到可拔插的 Vertex/Edge management module,对应 moudule 就可以对 runtime 执行计划进行调整。
Runtime 优化:任务运行时,程序知晓更多任务相关的信息,通过这些信息,我们可以动态修改修改执行计划,比如:修改 mapper 或 reducer 数量,决定何时启动 reducer 等。在 Tez 中,不同组件通过不同事件类型,进行通信。动态修改 reducer 并行度:MapTask 通过 VertexManager 类型的事件向 ShuffleVertextManager 发送信息,比如:所处理的 partition 大小等。 ShuffleVertexManager 通过所获得的信息,可以估算出所有 Task 的输出数据大小,最后来调整下游 reduce Vertex 的并行度,如下图:
reducer"慢"启动(预先启动): 上游 MapTask 通过事件不断向 ShuffleVertexManager 汇报任务完成情况,ShuffleVertexManager 通过这些信息,可以判断何时启动下游 reduceTask 与需要启动的 reduceTask 数量。
从逻辑执行计划到物理执行计划:从逻辑 DAG 到最后物理执行计划示意图:
Container 复用问题:container 的资源兼容? 被先后调度到同一个 container 的多个 task 所需要的资源,必须与 container 的资源相互兼容。也就是说,container 拥有的资源,如:jar 包,Memory,CPU 等,需要是 task 所需资源的“超集”。怎么调度? 进行 container 复用时,Tez 对 Task 进行调度。Tez 会依据:任务本地性、任务所需资源、pending 任务的优先级等因素,进行任务调度。优点:减少作业执行过程中 JVM 的创建与销毁带来的开销减小对 RM 的请求压力
4. Hive 如何添加相应的 Tez
一开始选用 0.92 的 tez,执行 insert 语句报错:
更换为对应的 0.84 版本后正常。
5. 总结
Tez 的原理决定了 会比较耗 CPU 与 Mem.这里给到了一定的解答
版权声明: 本文为 InfoQ 作者【InfoQ_Springup】的原创文章。
原文链接:【http://xie.infoq.cn/article/6e0ef97fcad0c40057a30fb57】。文章转载请联系作者。
评论