如何有效地将大型.tsv文件上载到pyspark中具有拆分列的Hive表中?

时间:2019-08-08 11:45:06

标签: python hive pyspark

我有一个很大的(.10百万行).tsv文件,其中有两列“ id”和“ group”。 “组”列实际上是某个ID所属的所有组的列表,因此文件如下所示:

id1     group1,group2
id2     group2,group3,group4
id3     group1
...

我需要使用pyspark将其上传到Hive表中,但是我想拆分组列,以使一行中只有一个组,所以结果表如下所示:

id1    group1
id1    group2
id2    group2
id2    group3
id2    group4
id3    group1

我尝试逐行读取行,仅使用python split()拆分列,然后为每一行创建spark数据框,并将其与每次迭代合并。我的代码可以运行,但是效率极低,因为它需要2分钟才能处理1000行。我的代码如下:

fields = [StructField('user_id', StringType(), True),StructField('group_id', StringType(), True)] 
membership_schema = StructType(fields) 

result_df = sqlContext.createDataFrame(sc.emptyRDD(), membership_schema)

with open('file.tsv','r') as f:
    for line in f:
        parts = line.split()
        id_part = parts[0]
        audience_parts = parts[1].split(',')
        for item in audience_parts:
            newRow = sqlContext.createDataFrame([(id_part,item)], membership_schema)
            result_df = result_df.union(newRow)
df_writer = DataFrameWriter(result_df)
df_writer.insertInto("my_table_in_hive")

是否有一种更简便,更有效的方式将整个文件上传到表中,而无需遍历行?

感谢帮助。

1 个答案:

答案 0 :(得分:2)

我看了看上面代码的计划,看来它正在扫描很多东西,并且也没有为您提供Spark的并行性。 您可以使用spark本机方法将文件数据读取到更多分区中,并控制它们在分区之间均匀分布数据。

df = sc.textFile(file_path,10).map(lambda x: x.split()).map(lambda x :(x[0],x[1].split(","))).toDF(['id','group'])
from pyspark.sql.functions import explode
newdf = df.withColumn("group", explode(df.group))

newdf.write.format("orc").option("header", "true").mode("overwrite").saveAsTable('db.yourHivetable')

此外,您可以增加或减少要爆炸的分区的大小,也可以控制随机播放的分区。

spark.conf.set("spark.sql.files.maxPartitionBytes","30")
spark.conf.set("spark.sql.shuffle.partitions", "100")