什么是Transform
会使用Python做数据处理的小伙伴一定使用过自己定义的函数去加工处理数据。在hive中的自定义函数支持Transform和UDF。UDF是将java代码打包上传,如果你不想或不会写java代码也可以,那就用到了Transform,写一个脚本,通过脚本(Python、shell)来处理数据。
transform的原理可以追溯到Hadoop的Streaming架构,Hadoop Streaming框架,最大的好处是,让任何语言编写的map, reduce程序能够在hadoop集群上运行;map/reduce程序只要遵循从标准输入stdin读,写出到标准输出stdout即可。其次,容易进行单机调试,通过管道前后相接的方式就可以模拟streaming, 在本地完成map/reduce程序的调试。
那么transform本质上也是一种Streaming,Hive用户可以使用Transform关键字在字符数据流中插入自己定义的map和reduce程序。在使用Transform的时候,默认情况下,在数据输入到用户自定义的脚本之前,列将转换为STRING并由TAB分隔;
类似地,所有NULL值都将转换为文本字符串\N,以便区分NULL值和空字符串。用户脚本的标准输出将被视为TAB分隔的STRING列,任何仅包含\N的单元格将被重新解释为NULL,然后生成的STRIG列将以通常的方式转换为表声明中指定的数据类型。用户脚本可以将调试信息输出为标准错误,该错误将显示在hadoop的任务详细信息页面上。
本位采用Python这个在数据科学应用较多的语言去写脚本,Python如何获取Hive传入的数据呢?Python中是有标准输入这样的东东的,它在sys模块中。我们获取数据的代码可以这样写:
import sys
for line in sys.stdin:
pass # 后续写我们的处理逻辑就可以了
Hive会自动把数据传过来,各个列之间由TAB间隔,也就是\t。
引用官方示例说明使用方法:
这是一个类似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