写在前面
使用SparkSQL读取数据库数据并返回dataframe,感觉都要被各种示例写烂了,本文大体上是没有新意的,只不过加了些细节,对需要的人的而言还是比较重要的。
此外,示例方法均是使用Java编写,为什么不用Scala呢,实在是语法糖对于我这样的水平最多只到泛型为止的人而言,过于抽象了,过了一个月就不太记得之前写的是啥了,还是习惯明确对象。
正文
介绍下几块细节吧。
-
驱动使用getDriver方法获取,注意其中的hbase指的是phoenix而不是原生HBase。
-
使用sql语句获取数据并进行处理。答案就在dbtable参数中传入sql 语句并且sql语句需要包裹一层,并且另起一个别名作为表名。
option("dbtable", "(select * from table) wangleai")
- 在使用oracle的时候,可以使用sessionInitStatement参数在会话创建之后读取数据之前,执行自定义sql语句,一般用于修改会话的相关配置。注意此参数只有在2.3版本以上才有。官网链接
至于我代码里写的sql的作用,那是用来改变日期类型和时间戳类型的默认时间格式,这样在sql语句里就可以直接这么写了(用于增量是巨好用的)。
option("oracle.jdbc.mapDateToTimestamp", "false").option("sessionInitStatement", initSql)
select * from table where datefield > '2019-11-01 00:00:00'
- 这个是重头戏了,那就是分区字段!如果需要获取并处理超大规模的数据时,建议一定要有分区字段,用于partitionColumn, numPartitions,lowerBound, upperBound这四个选项。
partitionColumn字段目前仅支持数字、日期或者时间戳,用于Spark程序使用此字段内容将数据分成多个区块去执行。numPartitions决定了要分成多少个区域,lowerBound和upperBound分别使用partitionColumn的上届和下届,配合numPartitions决定每个区域使用哪些数据。
注意的是,partitionColumn, lowerBound, upperBound三者必须同时出现。而且使用分区字段时,查询的sql语句也需要加入分区字段。
(代码示例中使用的是一个自增长的数字类型ID作为分区字段)
option("lowerBound", minNum).option("upperBound", maxNum).option("numPartitions", numPartitions + "").option("partitionColumn", partitionField)
- 然后就是代码了:
public static void main(String[] args) {
//自己设置Spark配置O!
SparkConf conf = new SparkConf().setAppName("wangleai");
SparkSession spark = SparkSession.builder().config(conf).getOrCreate();
Map<