19

我已经使用 Spark SQL 注册了一个临时表,如[本节]中所述:

people.registerTempTable("people")
// I can run queries on it all right.
val teenagers = sqlContext.sql("SELECT name FROM people WHERE age >= 13 AND age <= 19")

现在我想通过 JDBC 远程访问这个表。我按照[this other section]中的描述启动 Thrift 服务器。

./sbin/start-thriftserver.sh --master spark://same-master-as-above:7077

但该表不可见。

0: jdbc:hive2://localhost:10000> show tables;         
+---------+
| result  |
+---------+
+---------+
No rows selected (2.216 seconds)

我猜这是因为表是“临时的”(即与SqlContext对象的生命周期相关联)。但是如何制作非临时表?

我可以通过 Thrift 服务器查看Hive 表,但我不知道如何公开这样的 RDD。我发现一条评论表明我不能。

还是应该在我的应用程序中使用自己的 Thrift Server 运行SqlContext?它周围的几乎所有类都是private,并且这段代码不在 Maven Central 中(据我所知)。我应该使用HiveThriftServer2.startWithContext吗?它是无证的@DeveloperApi,但可能有效。

4

4 回答 4

17

很可能您已经解决了这个问题。但我最近尝试了一个类似的用例,并想分享我的发现。要通过 JDBC 公开 Spark 数据,您需要执行以下操作:

  • 启动 Spark 附带的 thrift-server(我使用的是 1.3.1 版),带有 Hive 的 thrift-server 也可以工作,但我还没有测试过

    /opt/mapr/spark/spark-1.3.1/sbin/start-thriftserver.sh --master spark://spark-master:7077 --hiveconf hive.server2.thrift.bind.host spark-master --hiveconf hive.server2.trift.port 10001

确保您没有将“localhost”而是将服务器的实际 ip-address/dnsname 提供给“hive.server2.thrift.bind.host”,否则您无法从其他主机连接到此 thrift 服务器

  • Beeline 是 Hive 和 Spark 附带的一个简单的 JDBC 客户端。启动beeline并将其连接到您的thrift服务器

SPARK_HOME/bin/beeline

直线>!连接 jdbc:hive2://spark-master:10001

  • 您可以在这里使用任何 hiveql 将您想要的数据加载到表中,但是 sql 将在 Spark 集群中执行

    使用 org.apache.spark.sql.parquet 选项创建临时表推文(路径 'maprfs:///path-to-your-parquet-files/');

  • 将表缓存在 Spark 内存中

缓存表推文

  • 就是这样,您的所有数据现在都缓存在 spark 集群中,您可以通过远程 jdbc 以低延迟查询它

  • jdbc 编码与编写任何 hive jdbc 代码完全相同,因为 thrift 服务器理解 hiveql 并将其转换为 spark sql。在此处查找 hive jdbc 示例:

https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-ConnectionURLs

对于用户名,您可以在 thrift-server 机器中提供任何 linux 用户名并将密码留空(这是非安全模式,如果需要,您可以使事情更安全)

  • 由于该表未在配置单元元存储中注册,因此表“推文”将不可见,因为该表未在配置单元元存储中注册,但您可以通过 jdbc 对表执行所有 sql 查询

  • 您可以使用 Spark 将数据缓存在内存中并通过远程 jdbc/odbc 进行查询。这将产生低延迟响应,对于大约 40 GB 的数据大小,我得到了 <2 秒的响应。但是,缓存不适用于真正的大数据,例如 tera 字节。在这种情况下,避免使用“cache table ...”命令,您仍然可以使用远程 jdbc/odbc,但响应不会在低延迟范围内

一切顺利!

MK

于 2015-07-10T15:07:01.140 回答
4

修改spark-defaults.conf并添加spark.sql.hive.thriftServer.singleSession true.

这允许 Thrift 服务器直接查看基于 RDD 的临时表,而无需保存表。您也可以CACHE TABLE XXX AS <query>在 Spark SQL 中执行并通过 ODBC/JDBC 公开它。

于 2016-08-25T16:09:16.433 回答
3

来自SPARK-3675

邮件列表中的一个常见问题是如何通过 JDBC 从临时表中读取数据。虽然我们应该在 SQL 中尝试并支持其中的大部分内容,但通过 JDBC 查询通用 RDD 也很不错。

并且解决方案(在 Spark 1.2.0 中出现)确实是使用HiveThriftServer2.startWithContext.

于 2014-11-25T12:15:53.907 回答
3

临时表背后的一般想法,至少从最初的 RDBMS 意图来看是它的范围非常有限,通常是用户会话,并且超出范围并在会话结束时被清理。

如果您在一个会话中创建临时表,那么通过 JDBC 或 ODBC 连接到 thriftserver 的另一个会话将无法看到它,这是设计使然。如果您需要一个表在会话之外持续存在,那么根据定义它不是临时的。

建议“启用 spark.sql.hive.thriftServer.singleSession 以便与您的 SQL 客户端共享它们”的解决方案可行,但有点违背了拥有多会话环境的目的。设置单个会话有效地强制临时表表现为持久表,但如果 hive 元存储重新启动,它们仍将脱离上下文。

使用 SqlContext 来创建表很容易,或者使用 saveAsTable() 参见:https ://spark.apache.org/docs/1.6.0/sql-programming-guide.html#saving-to-persistent-tables

编辑,在 spark 1.3 文档中似乎首先提到了 saveAsTable,但如果您使用的是早期版本,则可以使用 inlineSQL 方法。

people.write.saveAsTable("people")

这会将 people 表保存在您的默认数据库中。最好先创建一个数据库并指定它:

people.write.saveAsTable("databaseName.people")

或使用内联 SQL

sqlContext.sql("CREATE TABLE IF NOT EXISTS people
as SELECT name FROM people WHERE age >= 13 AND age <= 19")

这两种方法都将在 hive 元存储中注册持久表。saveAsTable 还具有关于是否要追加或覆盖的选项

于 2016-06-15T06:53:01.640 回答