我已将 HDFS 中的镶木地板表加载到 DataFrame 中:
val df = spark.read.parquet("hdfs://user/zeppelin/my_table")
我现在想要将此表公开给 Spark SQL,但这必须是一个永久表,因为我想从 JDBC 连接或其他 Spark 会话访问它。
快速的方法可能是调用df.write.saveAsTable方法,但在这种情况下,它将具体化 DataFrame 的内容并创建指向 Hive 元存储中的数据的指针,从而在 HDFS 中创建数据的另一个副本。
我不想拥有相同数据的两个副本,因此我希望创建一个外部表来指向现有数据。
要创建 Spark 外部表,您必须指定 DataFrameWriter 的“path”选项。像这样的东西:
df.write.
option("path","hdfs://user/zeppelin/my_mytable").
saveAsTable("my_table")
Run Code Online (Sandbox Code Playgroud)
但问题是,它会清空你的 hdfs 路径,hdfs://user/zeppelin/my_mytable消除你现有的文件,并会导致org.apache.spark.SparkException: Job aborted.. 这看起来像是 Spark API 中的一个错误......
不管怎样,解决方法(在 Spark 2.3 中测试)是从 Spark DDL 创建一个外部表。如果您的表有很多列,那么创建 DDL 可能会很麻烦。幸运的是,从 Spark 2.0 开始,您可以调用 DDLSHOW CREATE TABLE让 Spark 来完成繁重的工作。问题是您实际上可以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)
Run Code Online (Sandbox Code Playgroud)
您将得到如下 DDL:
CREATE TABLE `my_table_tmp` (`ID` INT, `Descr` STRING)
USING parquet
OPTIONS (
`serialization.format` '1',
path 'hdfs:///user/zeppelin/my_table_tmp')
Run Code Online (Sandbox Code Playgroud)
您希望将其更改为具有表的原始名称和原始数据的路径。您现在可以运行以下命令来创建指向现有 HDFS 数据的 Spark 外部表:
spark.sql("""
CREATE TABLE `my_table` (`ID` INT, `Descr` STRING)
USING parquet
OPTIONS (
`serialization.format` '1',
path 'hdfs:///user/zeppelin/my_table')""")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15023 次 |
| 最近记录: |