spark 读取clickhouse 非数值型字段并行分区设置
spark jdbc读取clickhouse
用spark采用jdbc读取clickhouse,mysql等数据库时,可以根据Long型设置分区字段,如下:
def jdbc(
url: String,
table: String,
columnName: String, # 根据该字段分区,需要为整形,比如id等
lowerBound: Long, # 分区的下界
upperBound: Long, # 分区的上界
numPartitions: Int, # 分区的个数
connectionProperties: Properties): DataFrame
也可根据具体的字段
jdbc(
url: String,
table: String,
predicates: Array[String],
connectionProperties: Properties): DataFrame
但是当选择的字段比较多时,连接数会很大,运行一段时间会有拒绝连接的风险。
解决的办法是对字段Array进行分组,并用 in 操作来进行分区,具体如下:
//JDBC分区信息
//grouped 对数组进行分组,每组4个
val typeIdArray =
Array(
"201c51890000000001000000000000000000000040",
"201c51890000000001000000000000000000000041",
……
"201c51890000000001000000000000000000000046")
.grouped(4)
.map(x => "typeId in ('" + x.mkString("','") + "')").toArray
val readData = spark.read
.jdbc(url, table, predicates, prop)
//前面设置了分区后,读数时不需要再设置typeid in 了。
readData.select(
col("ts_date"),
col("deviceId"),
col("typeId"),
col("value"))
.where(col("ts_date").===(partitiondate))
重点的设置在.map(x => “typeId in (’” + x.mkString("’,’") + “’)”).toArray 中,一定要对分组拼接一下,并按sql语法组成条件,实际执行时,spark会自动把这个信息加载到后面的select中。
在clickhouse中,可以查看具体连接的query
SELECT query_id,read_rows,elapsed,client_hostname,query From system.processes ;