基于jdbc数据源的Spark SQL持久化视图



我想在spark-sql中创建一个持久(全局(视图,该视图从底层jdbc数据库连接获取数据。当我使用如下所示的临时(会话范围(视图时,它工作得很好,但当尝试创建常规(持久和全局(视图时失败。

我不明白为什么后者不起作用,但找不到任何文档/提示,因为所有示例都是用临时视图完成的。从技术上讲,我不明白为什么它不应该工作,因为数据是在临时视图中从jdbc源中正确检索的,因此如果我想";存储";持久视图中的查询,这样无论何时调用视图,它都会直接从jdbc源中检索数据。

配置。

tbl_in = myjdbctable
tbl_out = myview
db_user = 'myuser'
db_pw = 'mypw'
jdbc_url = 'jdbc:sqlserver://myserver.domain:1433;database=mydb'

这是有效的。

query = f"""
create or replace temporary view {tbl_out}
using jdbc
options(
dbtable '{tbl_in}',
user '{db_user}',
password '{db_pw}',
url '{jdbc_url}'
)
"""
spark.sql(query)
> DataFrame[]

这不起作用。

query = f"""
create or replace view {tbl_out}
using jdbc
options(
dbtable '{tbl_in}',
user '{db_user}',
password '{db_pw}',
url '{jdbc_url}'
)
"""
spark.sql(query)
> ParseException:

错误。

ParseException: 
mismatched input 'using' expecting {'(', 'UP_TO_DATE', 'AS', 'COMMENT', 'PARTITIONED', 'TBLPROPERTIES'}(line 3, pos 0)
== SQL ==
create or replace view myview
using jdbc
^^^
options(
dbtable 'myjdbctable',
user 'myuser',
password '[REDACTED]',
url 'jdbc:sqlserver://myserver.domain:1433;database=mydb'
)

TL;DR:jdbc源代码上的spark-sql表的行为类似于视图,因此可以像视图一样使用。

我对sparksql中jdbc表的假设似乎有缺陷。事实证明,具有jdbc源(即通过using jdbc创建(的sql表实际上是针对jdbc源的实时查询(而不是我假设的在创建表期间的一次性jdbc查询(。在我看来,它实际上表现得像一个视图。这意味着,如果底层jdbc源发生更改(例如,列中的新条目(,则在读取时(例如,从中选择(,这将反映在spark-sql表中,而无需重新创建该表。

因此,jdbc源代码上的spark-sql表满足了我的要求,即在jdbc源中始终对底层表/sql对象进行可更新的反射。通常,我会使用一个视图。也许这就是为什么jdbc源上没有持久视图,而只有临时视图的原因(当然,由于它们是会话范围的,所以这些视图仍然有意义(。需要注意的是,spark-sqljdbc表的行为类似于一个可能令人惊讶的视图,特别是:

  • 如果在底层jdbc表中添加一列,它将不会显示在sparksql表中
  • 如果从底层jdbc表中删除一列,则在访问sparksql表时将发生错误(假设删除的列在创建sparksql表格期间存在(
  • 如果删除底层jdbc表,则访问sparksql表时将发生错误

spark.sql的输入应该是DML(数据操作语言(。它的输出是一个数据帧。

就最佳实践而言,应避免在spark.sql中使用DDL(数据定义语言(。即使某些语句可能有效,也不应以这种方式使用
如果要使用DDL,只需使用python包连接到数据库即可。

如果你想在spark中创建一个临时视图,可以使用spark语法createTempView

最新更新