繁体   English   中英

在 Hive 中将 Spark 数据帧另存为动态分区表

[英]Save Spark dataframe as dynamic partitioned table in Hive

我有一个示例应用程序可以将 csv 文件读取到数据帧中。 可以使用df.saveAsTable(tablename,mode)方法将数据帧以镶木地板格式存储到 Hive 表中。

上面的代码工作正常,但我每天都有很多数据,我想根据创建日期(表中的列)动态分区配置单元表。

有没有办法动态分区数据帧并将其存储到配置单元仓库。 想要避免使用hivesqlcontext.sql(insert into table partittioin by(date)....)对插入语句进行硬编码。

问题可以看作是对以下问题的扩展: 如何将DataFrame直接保存到Hive?

任何帮助深表感谢。

我相信它的工作原理是这样的:

df是一个包含年、月和其他列的数据框

df.write.partitionBy('year', 'month').saveAsTable(...)

或者

df.write.partitionBy('year', 'month').insertInto(...)

我能够使用df.write().mode(SaveMode.Append).partitionBy("colname").saveAsTable("Table")写入分区的配置单元表

我必须启用以下属性才能使其工作。

hiveContext.setConf("hive.exec.dynamic.partition", "true")
hiveContext.setConf("hive.exec.dynamic.partition.mode", "nonstrict")

我也面临同样的事情,但使用以下技巧我解决了。

  1. 当我们将任何表进行分区时,分区列变得区分大小写。

  2. 分区列应以相同的名称出现在 DataFrame 中(区分大小写)。 代码:

     var dbName="your database name" var finaltable="your table name" // First check if table is available or not.. if (sparkSession.sql("show tables in " + dbName).filter("tableName='" +finaltable + "'").collect().length == 0) { //If table is not available then it will create for you.. println("Table Not Present \\n Creating table " + finaltable) sparkSession.sql("use Database_Name") sparkSession.sql("SET hive.exec.dynamic.partition = true") sparkSession.sql("SET hive.exec.dynamic.partition.mode = nonstrict ") sparkSession.sql("SET hive.exec.max.dynamic.partitions.pernode = 400") sparkSession.sql("create table " + dbName +"." + finaltable + "(EMP_ID string,EMP_Name string,EMP_Address string,EMP_Salary bigint) PARTITIONED BY (EMP_DEP STRING)") //Table is created now insert the DataFrame in append Mode df.write.mode(SaveMode.Append).insertInto(empDB + "." + finaltable) }

它可以通过这种方式在SparkSession上配置:

spark = SparkSession \
    .builder \
    ...
    .config("spark.hadoop.hive.exec.dynamic.partition", "true") \
    .config("spark.hadoop.hive.exec.dynamic.partition.mode", "nonstrict") \
    .enableHiveSupport() \
    .getOrCreate()

或者您可以将它们添加到 .properties 文件

Spark 配置(至少在 2.4 中)需要spark.hadoop前缀,以下是 Spark 设置此配置的方式:

  /**
   * Appends spark.hadoop.* configurations from a [[SparkConf]] to a Hadoop
   * configuration without the spark.hadoop. prefix.
   */
  def appendSparkHadoopConfigs(conf: SparkConf, hadoopConf: Configuration): Unit = {
    SparkHadoopUtil.appendSparkHadoopConfigs(conf, hadoopConf)
  }

这对我有用。 我设置了这些设置,然后将数据放入分区表中。

from pyspark.sql import HiveContext
sqlContext = HiveContext(sc)
sqlContext.setConf("hive.exec.dynamic.partition", "true")
sqlContext.setConf("hive.exec.dynamic.partition.mode", 
"nonstrict")

这对我使用 python 和 spark 2.1.0 有用。

不确定这是否是最好的方法,但它有效......

# WRITE DATA INTO A HIVE TABLE
import pyspark
from pyspark.sql import SparkSession

spark = SparkSession \
    .builder \
    .master("local[*]") \
    .config("hive.exec.dynamic.partition", "true") \
    .config("hive.exec.dynamic.partition.mode", "nonstrict") \
    .enableHiveSupport() \
    .getOrCreate()

### CREATE HIVE TABLE (with one row)
spark.sql("""
CREATE TABLE IF NOT EXISTS hive_df (col1 INT, col2 STRING, partition_bin INT)
USING HIVE OPTIONS(fileFormat 'PARQUET')
PARTITIONED BY (partition_bin)
LOCATION 'hive_df'
""")
spark.sql("""
INSERT INTO hive_df PARTITION (partition_bin = 0)
VALUES (0, 'init_record')
""")
###

### CREATE NON HIVE TABLE (with one row)
spark.sql("""
CREATE TABLE IF NOT EXISTS non_hive_df (col1 INT, col2 STRING, partition_bin INT)
USING PARQUET
PARTITIONED BY (partition_bin)
LOCATION 'non_hive_df'
""")
spark.sql("""
INSERT INTO non_hive_df PARTITION (partition_bin = 0)
VALUES (0, 'init_record')
""")
###

### ATTEMPT DYNAMIC OVERWRITE WITH EACH TABLE
spark.sql("""
INSERT OVERWRITE TABLE hive_df PARTITION (partition_bin)
VALUES (0, 'new_record', 1)
""")
spark.sql("""
INSERT OVERWRITE TABLE non_hive_df PARTITION (partition_bin)
VALUES (0, 'new_record', 1)
""")

spark.sql("SELECT * FROM hive_df").show() # 2 row dynamic overwrite
spark.sql("SELECT * FROM non_hive_df").show() # 1 row full table overwrite

df1.write.mode("append").format('ORC').partitionBy("date").option('path', '/hdfs_path').saveAsTable("DB.Partition_tablename")

它将创建具有“日期”列值的分区,并且还将从 spark DF 写入配置单元中的配置单元外部表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM