使用Python将多行插入Hive表

时间:2015-11-30 13:24:34

标签: python hive

Hive是一个数据仓库,用于查询和聚合驻留在HDFS上的大型数据集。

标准INSERT INTO语法表现不佳,因为:

  1. 每个语句都需要执行Map / Reduce进程。
  2. 每个语句都会导致一个新文件被添加到HDFS中 - 随着时间的推移,这将导致从表中读取时性能非常差。
  3. 话虽如此,现在有一个Hive / HCatalog的Streaming API,详见here

    我面临着使用Python将数据以速度方式插入Hive的需求。我知道pyhivepyhs2库,但它们似乎都没有使用Streaming API。

    有没有人成功设法让Python使用Streaming API向Hive插入许多行,这是怎么做到的?

    我期待您的见解!

1 个答案:

答案 0 :(得分:1)

Hive用户可以通过脚本流表来转换该数据: ADD FILE replace-nan-with-zeros.py;

SELECT
  TRANSFORM (...)
  USING 'python replace-nan-with-zeros.py'
  AS (...)
FROM some_table;

这是一个简单的Python脚本:

    #!/usr/bin/env python
    import sys

kFirstColumns= 7

def main(argv):

    for line in sys.stdin:
        line = line.strip();
        inputs = line.split('\t')

        # replace NaNs with zeros
        outputs = [ ]
        columnIndex = 1;
        for value in inputs:
            newValue = value
            if columnIndex > kFirstColumns:
                newValue = value.replace('NaN','0.0')
            outputs.append(newValue)
            columnIndex = columnIndex + 1

        print '\t'.join(outputs)

if __name__ == "__main__":
    main(sys.argv[1:])

Hive和Python

Python可以通过HiveQL TRANSFORM语句从Hive用作UDF。例如,以下HiveQL调用存储在streaming.py文件中的Python脚本。

基于Linux的HDInsight

添加文件wasb:///streaming.py;

SELECT TRANSFORM (clientid, devicemake, devicemodel)
  USING 'streaming.py' AS
  (clientid string, phoneLable string, phoneHash string)
FROM hivesampletable
ORDER BY clientid LIMIT 50;

基于Windows的HDInsight

添加文件wasb:///streaming.py;

SELECT TRANSFORM (clientid, devicemake, devicemodel)
  USING 'D:\Python27\python.exe streaming.py' AS
  (clientid string, phoneLable string, phoneHash string)
FROM hivesampletable
ORDER BY clientid LIMIT 50;

这是这个例子的作用:

1.文件开头的add file语句将streaming.py文件添加到分布式缓存中,因此群集中的所有节点都可以访问它。

2. SELECT TRANSFORM ... USING语句从hivesampletable中选择数据,并将clientid,devicemake和devicemodel传递给streaming.py脚本。

3. AS子句描述了从streaming.py

返回的字段

这里是HiveQL示例使用的streaming.py文件。

#!/usr/bin/env python

import sys
import string
import hashlib

while True:
  line = sys.stdin.readline()
  if not line:
    break

  line = string.strip(line, "\n ")
  clientid, devicemake, devicemodel = string.split(line, "\t")
  phone_label = devicemake + ' ' + devicemodel
  print "\t".join([clientid, phone_label, hashlib.md5(phone_label).hexdigest()])

由于我们正在使用流式传输,因此该脚本必须执行以下操作:

1.从STDIN读取数据。这是通过在此示例中使用sys.stdin.readline()来完成的。

2.使用string.strip(line," \ n")删除尾随换行符,因为我们只需要文本数据而不是行尾指示符。

3.进行流处理时,单行包含每个值之间带有制表符的所有值。所以string.split(line," \ t")可以用来分割每个标签的输入,只返回字段。

4.处理完成后,输出必须作为单行写入STDOUT,每个字段之间有一个制表符。这是通过使用print" \ t" .join([clientid,phone_label,hashlib.md5(phone_label).hexdigest()])来实现的。

5.这一切都发生在while循环中,这将重复直到没有读取行,此时break退出循环并且脚本终止。

除此之外,脚本只是连接devicemake和devicemodel的输入值,并计算连接值的哈希值。非常简单,但它描述了从Hive调用的任何Python脚本应该如何工作的基础知识:循环,读取输入直到没有更多,在选项卡中分开输入的每一行,处理,写一行制表符分隔输出。