我们如何在 SPARK 2.2.0 中将外部表转换为托管表?

Posted

技术标签:

【中文标题】我们如何在 SPARK 2.2.0 中将外部表转换为托管表?【英文标题】:How can we convert an external table to managed table in SPARK 2.2.0? 【发布时间】:2018-01-04 07:10:40 【问题描述】:

以下命令已成功将外部表转换为Spark 2.0.0 中的托管表:

ALTER TABLE table_name SET TBLPROPERTIES(EXTERNAL=FLASE);

然而,上述命令在Spark 2.2.0 中失败并出现以下错误:

查询错误:无法设置或更改保留的属性键: '外部';

【问题讨论】:

嘿@oushnik-dey 你能找到解决方案吗?我正在努力实现同样的目标。 我在 Spark 2.1.0 顺便说一句。 我可以使用 Pyspark 做到这一点。请参阅下面的答案。 ***.com/questions/57520227/… 【参考方案1】:

正如@AndyBrown 在评论中指出的那样,您可以选择放到控制台并在那里调用 Hive 语句。在 Scala 中,这对我有用:

import sys.process._
val exitCode = Seq("hive", "-e", "ALTER TABLE table_name SET TBLPROPERTIES(\"EXTERNAL\"=\"FALSE\")").!

我在使用 Spark 2.1.1 时遇到了这个问题,其中 @Joha 的回答不起作用,因为 spark.sessionState 由于被声明为惰性而无法访问。

【讨论】:

【参考方案2】:

在 Spark 2.2.0 中,您可以执行以下操作:

import org.apache.spark.sql.catalyst.TableIdentifier
import org.apache.spark.sql.catalyst.catalog.CatalogTable
import org.apache.spark.sql.catalyst.catalog.CatalogTableType

val identifier = TableIdentifier("table", Some("database"))
val oldTable = spark.sessionState.catalog.getTableMetadata(identifier)
val newTableType = CatalogTableType.MANAGED 

val alteredTable = oldTable.copy(tableType = newTableType)

spark.sessionState.catalog.alterTable(alteredTable)

【讨论】:

【参考方案3】:

问题是 spark-2.1 及更高版本的大小写敏感问题。

请尝试将 TBLPROPERTIES 设置为小写 -

    ALTER TABLE <TABLE NAME> SET TBLPROPERTIES('external'='false')

【讨论】:

虽然您已经更正了 false 的引用和拼写,但将其设为小写只会添加一个用户属性“external”设置为“false”,并将保留的属性“EXTERNAL”保留为“TRUE”(并保留表的外部状态)。您可以通过运行“DESCRIBE FORMATTED ”看到这一点。我和 OP 有同样的问题,无法解决(如果我找到了,我会发布并回答),但这不是答案。 @AndyBrown 您是否找到了解决 set external = false 的方法。正如您所描述的那样,我收到错误 org.apache.spark.sql.AnalysisException:无法设置或更改保留的属性键:'EXTERNAL'; @donald 之类的。我发现了一个针对我的用例非常具体的解决方法,我认为它不是这个问题的合适答案:因为我在 pyspark 中操作,所以我掉到 shell 并直接调用 hive 引擎来执行 SET 命令,这是因为错误只发生在火花上下文中。如果您认为这可能有用,很高兴在聊天中进行阐述。 嘿@AndyBrown,您能否详细说明您是如何解决此问题的?当我遇到同样的问题时,请发布您的答案/代码。谢谢!【参考方案4】:

我在使用 hive 外部表时遇到了同样的问题。我通过使用 hive Metastore 客户端将 hive Metastore 中的外部属性直接设置为 false 解决了这个问题

 Table table = hiveMetaStoreClient.getTable("db", "table");
 table.putToParameters("EXTERNAL","FALSE");
 hiveMetaStoreClient.alter_table("db", "table", table,true);

【讨论】:

您能否进一步详细说明如何从 Spark 2 访问 hiveMetaStoreClient?据我所知,您需要一个不再可用的 HiveConf。 表对象在 spark 2.3.0 中没有方法 putToParameters【参考方案5】:

我尝试了 scala databricks notebook 中的上述选项,并且 外部表已转换为 MANAGED 表,好的部分是 新表上 spark 的 desc 格式选项仍然是 显示要在我的 ADLS 上的位置。这是一个限制, spark 有,我们无法指定托管的位置 表。

到目前为止,我可以为此做一个截断表。希望在那里 是创建具有位置的托管表的更直接选项 由 spark sql 指定。

【讨论】:

以上是关于我们如何在 SPARK 2.2.0 中将外部表转换为托管表?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 HDP 中的 zeppelin-spark2 中将库安装到 python

如何在 ipython 中将 Spark RDD 转换为 pandas 数据帧?

如何在 ipython 中将 Spark RDD 转换为 pandas 数据帧?

如何在Apache Spark Java中将数组类型的数据集转换为字符串类型

如何在 Spark Streaming 中将 RDD 转换为 DataFrame,而不仅仅是 Spark

如何在 pyspark 中将 DenseMatrix 转换为 spark DataFrame?