Spark JDBC 中的伪列

Posted

技术标签:

【中文标题】Spark JDBC 中的伪列【英文标题】:Pseudocolumn in Spark JDBC 【发布时间】:2017-12-03 06:41:55 【问题描述】:

我正在使用查询从 mysql 中获取数据,如下所示:

var df = spark.read.format("jdbc")
         .option("url", "jdbc:mysql://10.0.0.192:3306/retail_db")
         .option("driver" ,"com.mysql.jdbc.Driver")
         .option("user", "retail_dba")
         .option("password", "cloudera")
         .option("dbtable", "orders")
         .option("partitionColumn", "order_id")
         .option("lowerBound", "1")
         .option("upperBound", "68883")
         .option("numPartitions", "4")
         .load() 

问题是,我可以在指定partitionColumnoption 中使用伪列(如Oracle 中的ROWNUM 或DB2 中的RRN(employeeno))吗?

如果不是,我们可以指定一个不是主键的分区列吗?

【问题讨论】:

【参考方案1】:

我可以使用伪列吗(如 Oracle 中的 ROWNUM 或 DB2 中的 RRN(employeeno))

TL;DR 可能没有。

虽然 Spark 不考虑 PRIMARY KEYUNIQUE 之类的约束条件,但对 partitionColumn 的要求非常重要,文档中没有明确说明 - 它必须确定性

每个执行程序都使用单独的事务获取自己的数据。如果数字列不是确定性的(稳定的,在事务之间保留),Spark 看到的数据状态可能会不一致,并且可能会重复或跳过记录。

因为ROWNUM 的实现通常是不稳定的(取决于不稳定的排序,并且会受到索引等功能的影响),所以partitionColumn 的选择并不安全。出于同样的原因,您不能使用随机数。

此外,一些供应商可能会进一步限制对伪列的允许操作,使它们不适合用作分区列。 For example Oracle ROWNUM

对大于正整数的 ROWNUM 值进行条件测试始终为假。

可能会静默失败,导致错误结果。

我们能否指定一个不是主键的分区列

可以,只要满足上述标准。

【讨论】:

【参考方案2】:

根据Spark's official documentation,partitionColumn 可以是任何数字列(不一定是主键列)。

partitionColumn 必须是相关表中的数字列。

参考:https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html

【讨论】:

请说得更具体一些——它可以是一个伪列吗?例如,像 Oracle ROWNUM ? 您是否尝试过在代码中使用 ROWNUM 而不是 order_id?

以上是关于Spark JDBC 中的伪列的主要内容,如果未能解决你的问题,请参考以下文章

浅析SQL Server数据库中的伪列以及伪列的含义

Oracle中的伪列

Oracle 的伪列

Spark JDBC伪列不起作用

Oracle数据库的伪列

oracle数据库基本操作