Hive的Transform功能以及Transform的坑

转载自:https://www.tuicool.com/articles/fuimmmQ

Hive的 TRANSFORM 关键字提供了在SQL中调用自写脚本的功能,适合实现Hive中没有的功能又不想写UDF的情况。例如,按日期统计每天出现的 uid 数,通常用如下的SQL

SELECT date, count(uid)
FROM xxx
GROUP BY date

但是,如果我想在reduce阶段对每天的 uid 形成一个列表,进行排序并输出,这在Hive中没有现成的功能。那么,可以自写脚本实现该功能,并用 TRANSFORM 关键字调用

SELECT TRANSFORM(date, uid)
FROM xxx
CLUSTER BY date

这是一个类似streaming的功能,但是可以更方便的访问Hive中的数据,也可以把SQL语句和自写脚本整合在一起运行。

简单分析 官网 上的一个例子

FROM (
	FROM pv_users
	SELECT TRANSFORM(pv_users.userid, pv_users.date)
	USING 'map_script'
	AS dt, uid
	CLUSTER BY dt
) map_output
INSERT OVERWRITE TABLE pv_users_reduced
SELECT TRANSFORM(map_output.dt, map_output.uid)
USING 'reduce_script'
AS date, count;

这段代码的大致工作流程描述如下:

map_script 作为mapper, reduce_script 作为reducer。将 pv_users 表中的 userid , date两列作为mapper的输入字段,处理后的输出的前两个字段分别命名为 dt , uid ,并按照 dt 字段作partition和sort送给reduce阶段处理。reducer的输入字段为 dt 和 uid ,输出处理后的前两个字段,并命名为 date , count ,写入到 pv_users_reduced 表中。

这里有几个细节:

  • mapper和reducer用到的script可以是任何可执行文件。 注意 如果用到的是本地文件,应当在语句开始前用 ADD FILE 或 ADD FILES 将文件加入进来
  • mapper和reducer的输入输出都是以TAB为分隔符
  • 如果 USING ‘script’ 语句后面没有 AS ,则Hive默认 script 的输出中第一个TAB之前的字段为key,后面的部分全部为value。若指定了 AS ,则严格按照 AS 后面的字段数输出,例如AS dt, uid ,则输出前两个字段并忽略后面的字段。此外, AS 语句可以指定数据类型,如AS (date STRING, count INT) 。默认都是 string 类型。
  • CLUSTER BY 关键字是 DISTRIBUTE BY 和 SORT BY 的简写,这两者可以认为对应与Hadoop的partition和sort过程。如果partition和sort的key是不同的,可以使用 DISTRIBUTE BY 和 SORT BY 分别指定。
  • MAP 和 REDUCE 关键字是 SELECT TRANSFORM 关键字的别名,原文中给出了上面等价代码
    FROM (
    	FROM pv_users
    	MAP pv_users.userid, pv_users.date
    	USING 'map_script'
    	AS dt, uid
    	CLUSTER BY dt
    ) map_output
    INSERT OVERWRITE TABLE pv_users_reduced
    REDUCE map_output.dt, map_output.uid
    USING 'reduce_script'
    AS date, count;
    因此,原文中特别提醒, MAP 并没有强制产生一个map过程的作用, REDUCE 同理。只是为了阅读更清晰。

 

==========================================================================================

转载自:https://blog.csdn.net/u012802702/article/details/70199368

曾经为贪图方便使用Hive的tranform来实现了一些对数据的处理逻辑,但是之后发现各种坑啊,,,,,,如下:
      通过大量的数据实验发现:在数据清洗过程中,如果使用的是TransForm而不是UDF的话,因为Python是直接向系统申请资源的,而不是像ResourceManager申请资源,故会导致启动的Python脚本对内存和CPU的使用不可控,尤其是当启动多个Map时,因为一个map将启动一个Python因此,当同时运行的map有几十个时(测试集群较小),同时将尝试启动相同个数的python(资源够用的话仍然会启动几十个),且此时Map占用的内存是不会释放掉的他在一直等待Python的结果,这将导致python可用的资源仅仅是原本分配给系统的很少的资源(注:在安装Hadoop时,对于单个节点,一般仅仅给系统留出很少的内存,其他的内存全部分给了集群。例如32G物理内存的节点给系统和dataNode+nodeManager的内存就4-8个G,同时CPU核数也不足节点的一半,剩余的内存和cpu核数全部划分给集群使用。需要注意的是,这里虽然说是划分给集群使用,仅仅是逻辑上的划分,即规定集群可以使用的最大的物理内存,超过该内存时MR可以认为是不会抢占分配给系统+DataNode+nodeManager的内存的,但是当集群中没有MR在执行,即没有map或者reduce在执行时,划分给集群的这部分资源是可以被系统使用的。而若有map和Reduce在执行时,运行map和reduce的JVM的资源不会因为系统进程需要使用而被释放掉)所以,所有正在执行的Map一直在等待python的运行结果而没有释放掉其自身占用的资源,故python无法使用分配给集群的资源而只能使用预留给系统+nodeManager+DataNode的4-8G的内存和很少的cpu核数。因此会导致集群的资源无法被高效利用。

 

综上,使用Transform(Python)执行效率低的根本原因在于Python是直接向操作系统申请资源,而不是向YARN的ResourceManager申请资源,故而导致节点的资源无法高效组织和被利用。此外,不要轻易使用transform!不要轻易使用transform!不要轻易使用transform,,,

 

解决方案:

     1、将Transform的python代码的逻辑改成UDF来实现,因为使用Java来编写的UDF可以直接被运行map和Reduce的JVM所管理,这样整个流程的所有资源的分配个管理就可以全部由ResourceManager统一管理,资源的调度将更加合理,不会在出现不可控的情况。

     2、若之前的逻辑太多,太复杂,,等等各种原因导致只能使用Transform来实现, 那么可以在调用Hive sql 时添加hive参数设置,降低同时启动的map的个数(通常增加一个map需要处理的数据量,默认一个map仅仅处理一个block的数据,可以增大mix的大小),这样同时启动的python也会减少,且因为同时运行的map个数减少且没有达到集群所能使用的内存上限,也就是说此时向系统申请资源的python的个数减少,同时集群也会有空闲的内存借给系统(python)使用,变向的优化了资源的调度,提升 了节点内存的有效利用率。

     3、若所有的业务逻辑都是用TranSform实现的,不能修改,那么为了避免每次都像第2中方案那样修改参数,最有效的方案就是,根据当前情况(map需要处理的逻辑很简单,需要的内存不太大,更多的逻辑是在python中实现的)重新配置优化集群的参数,即适当增大预留给系统+DataNode+nodeManager的内存和Cpu核数,降低或避免 因系统可支配资源有限,导致的python无法向系统申请到足够资源而运行效率慢的问题。

 

 

 

补充扩展 内容:

     关于Hadoop集群的安装的内存分配问题,详情可以参考CDH的官方文档:https://www.cloudera.com/documentation/enterprise/5-3-x/topics/cdh_ig_yarn_tuning.html

首先简单的讲,假设当前物理节点运行DataNode和nodeManager,因为这是Hadoop集群中数量最多的节点也是需要资源配置考虑较多的节点,而控制节点例如安装Namenode或者ResourceManager的节点需要考虑的问题相对单一,故以下资源的配置仅仅是对于同时运行DataNode和NodeManager的节点配置而言,不过通常一般的Hadoop集群安装所有的节点配置是一样的(方便管理和分发)。 当前的物理节点仅仅用于安装Hadoop Hbase 等数据处理常用开源工具(zookeeper集群单独安装),而不会再安装和运行其他除系统服务外的服务,那么当前物理节点的资源(这里仅仅只内存和CPU)分配仅仅只需要考虑划两部分的的划分,各个部分所需要的内存和CPU:

一:系统本身需要的资源+DataNode需要的资源+NodeManager需要的资源

     这部分很简单,根据具体情况确定系统需要的资源+DataNode+NodeManager三个进程需要的资源相加即可。剩下的资源全部是分给集群运行MR

二:当前节点提供给hadoop集群的资源,即该节点的多大的资源分配给Hadoop集群运行MR程序使用。

     这里需要考虑几点,且各个参数的注意事项在官方文档中写的很详细,不再赘述。

1、Contain最小可使用的内存,和最大可以使用内存,以及当最小内存不够用时,在增加Contain内存的时候每次增加内存的步长,注:在启动Contain时默认直接分配给Contain的内存就是最小可使用内存。

2、APPMaster可以使用的核数和内存,

3、单个map和单个reduce需要占用的内存和cpu核数(Reduce内存一般是Map的两倍),以及初始化时分配给Map和Reduce的实际内存(一般是设置的内存的80%)

4、单个

注:对当前节点资源的管理是由NodeManager服务管理的(而整个集群所有可用资源的调度是由ResourceManager负责的),也就是说配置文件中可以通过配置参数来告诉NodeManager服务可以使用当前节点资源的上限有多大(即当前节点分配给Hadoop运行MR的资源),例如yarn.nodemanager.resource.cpu-vcores=16来告诉运行在当前节点的NodeManager,他可以使用当前节点16个cpu核(这个核不是物理核数而是虚拟核数,通常一个物理核可以虚拟化成4个虚拟核,故这里的16实际上对应的物理核只有4个,且当前节点的物理核需要大于4,毕竟要为操作系统+DataNode+NodeManager留一部分核),yarn.nodemanager.resource.memory-mb=20480告诉运行在当前节点的NodeManager,他可以使用当前机器上的内存上限是20G=2048M(注意这里当前节点的物理内存肯定大于20G,因为需要有一部分内存留给系统和DataNode+NodeManager使用) 用于创建Contain以执行AppMaster,Map,Reduce。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值