在Hadoop UDF输出中保留列数据类型(流)

时间:2014-06-12 01:05:37

标签: python hadoop hive apache-pig hadoop-streaming

我正在用Python编写一个UDF,用于Hadoop上的Hive查询。我的表格包含多个bigint字段和多个string字段。

我的UDF会修改bigint字段,将修改后的版本减去新列(也应该是数字),然后保留string字段。

当我在查询中运行UDF时,结果都是string列。

如何在UDF输出中保留或指定类型?


更多详情:

我的Python UDF:

import sys
for line in sys.stdin:
    # pre-process row
    line = line.strip()
    inputs = line.split('\t')

    # modify numeric fields, calculate new field
    inputs[0], inputs[1], new_field = process(int(inputs[0]), int(inputs[1]))

    # leave rest of inputs as is; they are string fields.

    # output row
    outputs = [new_field]
    outputs.extend(inputs)
    print '\t'.join([str(i) for i in outputs]) # doesn't preserve types!

我将此UDF保存为myudf.py并将其添加到Hive。

我的Hive查询:

CREATE TABLE calculated_tbl AS
SELECT TRANSFORM(bigintfield1, bigintfield2, stringfield1, stringfield2)
USING 'python myudf.py'
AS (calculated_int, modified_bif1, modified_bif2, stringfield1, stringfield2)
FROM original_tbl;

1 个答案:

答案 0 :(得分:1)

Streaming通过stdout发送所有内容。它实际上只是在引擎盖下的hadoop流媒体上的一个包装器。所有类型都转换为字符串,您在python udf中相应地处理它们,并作为字符串返回到hive。配置单元中的python变换永远不会返回除字符串之外的任何内容。您可以尝试在子查询中执行转换,然后将结果转换为类型:

 SELECT cast(calculated_int as bigint)
        ,cast( modified_bif1 as bigint)
        ,cast( modified_bif2 as bigint) 
        ,stringfield1 
        ,stringfield2
 FROM ( 
 SELECT TRANSFORM(bigintfield1, bigintfield2, stringfield1, stringfield2)
 USING 'python myudf.py'
 AS (calculated_int, modified_bif1, modified_bif2, stringfield1, stringfield2)
 FROM original_tbl) A ;

Hive可能会让你逃避这个,如果没有,你需要将结果保存到表中,然后你可以在另一个查询中转换(强制转换)为另一种类型。

它只是使用Java UDF的最终选项。仅映射UDF也不错,它们允许您指定返回类型。

更新(来自提问者):

上述答案非常有效。一个更优雅的解决方案,我发现阅读"编程蜂巢"几周后,Oℜ Reilly的书是:

CREATE TABLE calculated_tbl AS
SELECT TRANSFORM(bigintfield1, bigintfield2, stringfield1, stringfield2)
USING 'python myudf.py'
AS (calculated_int BIGINT, modified_bif1 BIGINT, modified_bif2 BIGINT, stringfield1 STRING, stringfield2 STRING)
FROM original_tbl;

您可以在AS(...)行中指定类型,而不是强制转换。