Spark read() 有效,但 sql() 抛出 Database not found

Posted

技术标签:

【中文标题】Spark read() 有效,但 sql() 抛出 Database not found【英文标题】:Spark read() works but sql() throws Database not found 【发布时间】:2017-01-11 04:22:05 【问题描述】:

我正在使用 Spark 2.1 从 Java 中的 Cassandra 读取数据。 我尝试了https://***.com/a/39890996/1151472 中发布的代码(使用 SparkSession),它成功了。但是,当我用 spark.sql() 替换 spark.read() 方法时,会引发以下异常:

Exception in thread "main" org.apache.spark.sql.AnalysisException: Table or view not found: `wiki`.`treated_article`; line 1 pos 14;
'Project [*]
+- 'UnresolvedRelation `wiki`.`treated_article`

    at org.apache.spark.sql.catalyst.analysis.package$AnalysisErrorAt.failAnalysis(package.scala:42)

我对 read 和 sql 方法使用相同的 spark 配置

read() 代码: 数据集数据集 =

spark.read().format("org.apache.spark.sql.cassandra")
                .options(new HashMap<String, String>() 
                    
                        put("keyspace", "wiki");
                        put("table", "treated_article");
                    
                ).load();

sql() 代码:

spark.sql("SELECT * FROM WIKI.TREATED_ARTICLE");

【问题讨论】:

【参考方案1】:

Spark Sql 使用Catalogue 来查找数据库和表引用。当您写入不在目录中的表标识符时,它将引发与您发布的错误类似的错误。 read 命令不需要目录,因为您需要在调用中指定所有相关信息。

您可以通过

向目录中添加条目

将数据集注册为视图

首先创建你的数据集

spark.read().format("org.apache.spark.sql.cassandra")
                .options(new HashMap<String, String>() 
                    
                        put("keyspace", "wiki");
                        put("table", "treated_article");
                    
                ).load();

然后使用目录注册功能之一

void    createGlobalTempView(String viewName)
Creates a global temporary view using the given name.
void    createOrReplaceTempView(String viewName)
Creates a local temporary view using the given name.
void    createTempView(String viewName)
Creates a local temporary view using the given name

或使用 SQL 创建语句

   CREATE TEMPORARY VIEW words
     USING org.apache.spark.sql.cassandra
     OPTIONS (
       table "words",
       keyspace "test",
       cluster "Test Cluster",
       pushdown "true"
     )

一旦通过其中一种方法添加到目录中,您就可以在该上下文发出的所有sql 调用中引用该表。


例子

CREATE TEMPORARY VIEW words
  USING org.apache.spark.sql.cassandra
  OPTIONS (
    table "words",
    keyspace "test"
  );

SELECT * FROM words;
// Hello    1
// World    2

Datastax(我的雇主)企业软件通过将条目放置在 Spark 用作目录的 Hive Metastore 中来自动注册所有 Cassandra 表。这使得无需手动注册即可访问所有表。

此方法允许在不附带CREATE VIEW 的情况下使用选择语句

【讨论】:

非常感谢 Russ .. 你让我很开心【参考方案2】:

我想不出一种方法来使这项工作脱离我的脑海。问题在于 Spark 不知道要尝试的格式,并且指定的位置由键空间占用。我能找到的与此类内容最接近的文档是 Cassandra 连接器文档的 here in the DataFrames section。您可以尝试指定 using 语句,但我认为这不会在 select 中起作用。所以,除此之外,你最好的选择是创建一个 PR 来处理这种情况,或者坚持阅读 DSL。

【讨论】:

以上是关于Spark read() 有效,但 sql() 抛出 Database not found的主要内容,如果未能解决你的问题,请参考以下文章

Spark 数据集显示架构但为 show() 方法抛出 UnsupportedOperation 异常

Spark sql注册的临时表不能在sqlContext.read()中使用?

Spark SQL 无法输出数据帧

实例化“org.apache.spark.sql.hive.HiveExternalCatalog”时出错

如何在 spark sql 连接条件中将字符串数据类型转换为日期:to_date 不起作用并且转换抛出错误

无法从 spark sql 插入配置单元分区表