Sql server 如何使用varchar数据类型的partitionColumn读取scala spark上的表?
是否可以指定varchar数据类型的partitionColumn? 我要读取的表没有主键,所有列都是varchar数据类型。有没有办法将partitionColumn作为varchar类型从jdbc中读取Sql server 如何使用varchar数据类型的partitionColumn读取scala spark上的表?,sql-server,scala,apache-spark,jdbc,Sql Server,Scala,Apache Spark,Jdbc,是否可以指定varchar数据类型的partitionColumn? 我要读取的表没有主键,所有列都是varchar数据类型。有没有办法将partitionColumn作为varchar类型从jdbc中读取 var finaldataframe = spark.read.format("jdbc") .option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver") .option("database",db) .option("u
var finaldataframe = spark.read.format("jdbc")
.option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
.option("database",db)
.option("url", url)
.option("dbtable", table_name)
.option("numPartitions", partitions)
.option("partitionColumn", pm_key)
.option("lowerbound", w_minLogID)
.option("upperbound", w_maxLogID)
.load()
spark docs说:
partitionColumn必须是相关表中的数字、日期或时间戳列
但是有一些解决方法吗?TL;DR此可选字段用于提高性能。如果数据集很小,可以跳过它。类似的功能可以通过为字符串列使用
谓词:Array[String]
参数来实现
val connectionProperties = new Properties()
connectionProperties.put("database", db)
connectionProperties.put("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
var finaldataframe = spark.read.jdbc(
url = url,
table = table_name,
predicates = Array[String]("columnA like 'A%'", "columnB like 'B%'" )
connectionProperties = connectionProperties
)
要理解为什么
partitionColumn
只允许使用类似数字的列,请查看spark如何从数据库中读取数据
默认情况下,spark将使用单个执行器连接到数据库,运行查询并开始提取结果。如果您希望从数据库中提取大型数据集,则此方法不适用,因为
- 只有一个执行器正在提取数据李>
- 提取的数据必须重新分区/洗牌给其他执行者
从产品中选择id、prod\u name
,并且此表有一百万行。您可以告诉spark
numPartitions
为4
,partitionColumn
为id
为整数,lowerbound
1和upperbound
为1000000
现在spark将计算每个执行者需要提取250K条记录 (上界-下界+1)/numPartitions
=(1000000-1+1)/4
=250000 使用此命令,第一个执行器将启动查询
select *
from
(
select id, prod_name
from products
)
where id >= 1 and id<=250000
及
为了在spark JDBC数据读取中实现并行性,必须指定numPartitions、partitionColumn、lowerBound和upperBound。()否则spark总是执行一个JDBC连接,并将所有数据读取到单个分区中。在这种情况下,只使用一个执行器,无法实现并行性。 例如 在这种情况下,只有一个查询被激发到其中一个执行器中的数据库,因此没有并行性。 要实现并行性,请使用以下代码
spark.sqlContext.read
.option("partitionColumn", "amount")
.option("lowerBound", 0).option("upperBound", 1000)
.option("numPartitions", 10)
.jdbc(url), "( select * from transaction ) as s", connectionProperties)
上述查询将在spark执行器之间创建10 db连接,并将数据并行读取到spark内存
select * from transaction where amount>=0 and amount<100.
select * from transaction where amount>=100 and amount<200...
上述代码将在spark执行器之间创建10 DB连接。
当我们在分区计数上对行数进行mod时,我们总是会得到从0到9的值。通过这样做,数据被并行读取,并均匀地分布在分区之间。
检查分区
import spark.implicits._
df
.rdd
.mapPartitionsWithIndex { case (i, rows) => Iterator((i, rows.size)) }
.toDF("partition_number", "number_of_records")
.show
spark.sqlContext.read.jdbc(url, "(select * from transaction ) as s", connectionProperties).
spark.sqlContext.read
.option("partitionColumn", "amount")
.option("lowerBound", 0).option("upperBound", 1000)
.option("numPartitions", 10)
.jdbc(url), "( select * from transaction ) as s", connectionProperties)
select * from transaction where amount>=0 and amount<100.
select * from transaction where amount>=100 and amount<200...
val partitionCount = 10
val partitionKey="partitionKey"
spark.sqlContext.read
.option("partitionColumn", partitionKey)
.option("lowerBound", 0).option("upperBound", partitionCount)
.option("numPartitions", partitionCount)
.jdbc(url), s"( select mod(row_number() OVER (),$partitionCount) as $partitionKey, * from transaction ) as s", connectionProperties).drop(partitionKey)
import spark.implicits._
df
.rdd
.mapPartitionsWithIndex { case (i, rows) => Iterator((i, rows.size)) }
.toDF("partition_number", "number_of_records")
.show