【Spark】SparkJdbc并发读取的partitionColumn规则
参考: spark 官方文档
使用spark的jdbc的方式读取数据的操作:
方式1:
spark.read.option(...).jdbc(url,table,properties)
方式2:
spark.fomat('jdbc').option(...).load()
可以注意到,在spark
通过jdbc
读取数据时候是有一个option
的选项的。
本次主要讨论spark jdbc
的多连接读取参数:
- partitionColumn
- lowerBound
- upperBound
- numPartitions
解释一下几个参数:
partitionColumn
这个参数是制定要用来分区查询的列,一般为可排序类型,比如: numeric
,date
, or timestamp
一般来说是可排序类型的列,有点像sqoop的分区抽取操作的设置。
lowerBound
,upperBound
共同用来决定分区的跨度。
numPartitions
设置spark jdbc
的最大并发度,其中如果开启这个功能,四个都是必要参数
这些参数可以写在option当中进行配置。
那么,它的现象是怎么样的?
假设有一张mysql
的表stu
,总共有3万数据。其中有一列id
为自增列。利用spark jdbc
读取数据的时候。
spark.fomat('jdbc')
.option("partitionColumn","id")
.option("lowerBound","100000")
.option("upperBound","200000")
.option("numPartitions",4)
.... //其他options
.load()
那么这个设置下的spark
是如何工作的?
根据option
中的numPartitions
,可以得知,这个spark jdbc
的连接最大可以有4个,
接着lowerBound
和upperBound
的控制下,spark
会生成如下4条sql
1. select * from stu where id<12500 and id is null
2. select * from stu where id>=12500 and id<15000
3. select * from stu where id>=15000 and id<17500
4. select * from stu where id>=17500
如果当这个 numPartitions
设置为5
时,spark
会生成如下几条sql
1. select * from stu where id<12000 and id is null
2. select * from stu where id>=12000 and id<14000
3. select * from stu where id>=14000 and id<16000
4. select * from stu where id>=16000 and id<18000
5. select * from stu where id>=18000
什么?你要是问我当numPartitions
设置为3的时候会生成什么sql?
select * from stu where id<13333 and id is null
select * from stu where id>=13333 and id<=16666
select * from stu where id>=16666
附源码位置:
org.apache.spark.sql.execution.datasources.jdbc.JDBCRelation#columnPartition
val stride: Long = upperBound / numPartitions - lowerBound / numPartitions
var i: Int = 0
val column = partitioning.column
var currentValue = lowerBound
val ans = new ArrayBuffer[Partition]()
while (i < numPartitions) {
val lBoundValue = boundValueToString(currentValue)
val lBound = if (i != 0) s"$column >= $lBoundValue" else null
currentValue += stride
val uBoundValue = boundValueToString(currentValue)
val uBound = if (i != numPartitions - 1) s"$column < $uBoundValue" else null
val whereClause =
if (uBound == null) {
lBound
} else if (lBound == null) {
s"$uBound or $column is null"
} else {
s"$lBound AND $uBound"
}
ans += JDBCPartition(whereClause, i)
i = i + 1
}
总结:
这个 spark
并发读取jdbc
的数据时候,一定是全表全量数据 大家可要记住了!!!但是如果真的需要读取全表全量数据的话,这样还挺快的,会提升效率。
如果在这里有什么写错的地方,请大佬多多指教,在评论区留言,谢谢各位了!!!