如何解决spark写hive慢的问题

本文探讨了在Spark中写入Hive表时遇到的性能问题,特别是INSERT OVERWRITE操作的耗时。通过将数据保存为Hive兼容的textfile格式并使用Hive的LOAD DATA命令,显著减少了写入时间。此外,还提到了针对ORC表的优化策略,包括创建临时表和使用SELECT插入,以实现更快的数据迁移。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用spark写hive过程中,发现最耗时的部分是将产生的结果写入hive,举个例子,对3g*1G表的join来讲,将结果使用以下方式直接写入hive表需要超过半小时的时间:

dataframe.registerTempTable("result")

sql(s"""INSERT OVERWRITE Table $outputTable PARTITION (dt ='$outputDate') select * from result""")

而整个结果数据的产生只需要4分钟左右的时间,比如以下方式:将结果以textfile存入hdfs:

result.rdd.saveAsTextFile(output_tmp_dir)

由此可见,对hive的写入操作耗用了大量的时间。

 

对此现象的优化可以是,将文件存为符合hive table文件的格式,然后使用hive load将产生的结果文件直接move到指定目录下。代码如下:

result.rdd.map { r => r.mkString("\001") }.repartition(partitions).saveAsTextFile(output_tmp_dir)

sql(s"""load data inpath '$output_tmp_dir' overwrite into table $output partition (dt='$dt')""")

详解:

  1. result.rdd.map { r => r.mkString("\001") }.repartition(partitions).saveAsTextFile(output_tmp_dir):
    hive column默认分隔符在scala/java中的表示为“/001”,r.mkString("/001")既是将column以分隔符/001进行分割,hive在导入时会自动识别。
    repartition(partitions)是为了防止hdfs中产生大量小文件。partitions的设定与最终结果大小有关,一般是result_size/hdfs_block_size。
  2. sql(s"""load data inpath '$output_tmp_dir' overwrite into table $output partition (dt='$dt')""")
    此处使用hive load data命令,将hdfs文件load到hive表中。后台操作为直接将目录下的文件移到hive table所在目录,所以只是hdfs move数据的过程,执行非常快。 
  3. 需要注意的是,此处要求hive建表时,已textfile格式建表。orc的方式不支持。对orc的表,可以建立临时表使用textfile临时存储,然后用以下命令进行导入:
    sql(s"""load data inpath '$output_tmp_dir' overwrite into table $tmp_table partition (dt='$dt')""")
    sql(s"""INSERT OVERWRITE Table $outputTable PARTITION (dt ='$outputDate') select * from $tmp_table where dt='$dt'""") 
    在资源配置为--num-executors 20 --executor-cores 4,结果数据为1.8g的情况下,需要额外耗时50s。好处是结果数据使用列式、压缩方式存储,压缩比12.7左右。

使用优化后的方式,原有test case的耗时从半小时降到4分钟,效率提升明显。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值