如何从hdfs中的数据创建外部spark表

dgiusagp  于 2021-06-26  发布在  Hive
关注(0)|答案(1)|浏览(433)

我已将hdfs中的Parquet表加载到Dataframe中: val df = spark.read.parquet("hdfs://user/zeppelin/my_table") 我现在想将这个表公开给sparksql,但这个表必须是持久的,因为我想从jdbc连接或其他spark会话访问它。
快速的方法是打电话 df.write.saveAsTable 方法,但在本例中,它将具体化Dataframe的内容,并在配置单元元存储中创建指向数据的指针,从而在hdfs中创建另一个数据副本。
我不想拥有相同数据的两个副本,所以我希望创建一个指向现有数据的外部表。

ajsxfq5m

ajsxfq5m1#

要创建spark外部表,必须指定dataframewriter的“path”选项。像这样:

df.write.
  option("path","hdfs://user/zeppelin/my_mytable").
  saveAsTable("my_table")

但问题是,它将清空hdfs路径 hdfs://user/zeppelin/my_mytable 删除现有文件并将导致 org.apache.spark.SparkException: Job aborted. . 这看起来像是spark api中的一个bug。。。
无论如何,解决方法(在spark2.3中测试)是从sparkddl创建一个外部表。如果您的表有许多列,那么创建ddl可能会很麻烦。幸运的是,从spark 2.0开始,您可以调用ddl SHOW CREATE TABLE 让斯帕克来做这项艰苦的工作。问题是你实际上可以运行 SHOW CREATE TABLE 在持久表中。
如果表非常大,我建议获取该表的示例,将其持久化到另一个位置,然后获取ddl。像这样:

// Create a sample of the table 
val df = spark.read.parquet("hdfs://user/zeppelin/my_table")
df.limit(1).write.
    option("path", "/user/zeppelin/my_table_tmp").
    saveAsTable("my_table_tmp")

// Now get the DDL, do not truncate output
spark.sql("SHOW CREATE TABLE my_table_tmp").show(1, false)

你会得到一个ddl,比如:

CREATE TABLE `my_table_tmp` (`ID` INT, `Descr` STRING)
USING parquet
OPTIONS (
  `serialization.format` '1',
  path 'hdfs:///user/zeppelin/my_table_tmp')

您希望将其更改为表的原始名称和原始数据的路径。现在可以运行以下命令来创建指向现有hdfs数据的spark外部表:

spark.sql("""
  CREATE TABLE `my_table` (`ID` INT, `Descr` STRING)
  USING parquet
  OPTIONS (
    `serialization.format` '1',
    path 'hdfs:///user/zeppelin/my_table')""")

相关问题