有没有办法限制使用spark sql 2.2.0从jdbc源获取的记录数?
我正在处理从一个MS Sql Server表到另一个MS Sql Server表中移动(和转换)大量记录> 200M的任务:
val spark = SparkSession
.builder()
.appName("co.smith.copydata")
.getOrCreate()
val sourceData = spark
.read
.format("jdbc")
.option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
.option("url", jdbcSqlConnStr)
.option("dbtable", sourceTableName)
.load()
.take(limit)
虽然它有效,但显然首先从数据库中加载所有200M记录,然后首先加载18分钟,然后返回我想要测试和开发的有限数量的记录。
切换take(...)和load()会产生编译错误。
我很欣赏有办法将样本数据复制到较小的表格,使用SSIS或其他etl工具。
我真的很好奇是否有办法使用spark,sql和jdbc实现我的目标。
答案 0 :(得分:1)
这种方法对于关系数据库来说有点不好。 spark的加载函数将请求您的完整表,存储在内存/磁盘中,然后执行RDD转换和执行。
如果您想进行探索性工作,我建议您在第一次加载时存储这些数据。有几种方法可以做到这一点。拿你的代码,然后这样做:
val sourceData = spark
.read
.format("jdbc")
.option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
.option("url", jdbcSqlConnStr)
.option("dbtable", sourceTableName)
.load()
sourceData.write
.option("header", "true")
.option("delimiter", ",")
.format("csv")
.save("your_path")
这将允许您将本地计算机中的数据保存为CSV,这是您可以使用任何语言进行探索的最常用格式。 每次要加载时,请从此文件中获取此数据。如果你想要实时分析,或者像这样的任何其他事情。我建议您使用数据转换构建一个管道来更新另一个存储。使用这种方法每次处理从数据库加载的数据都不好。
答案 1 :(得分:1)
对于下载行的限制数量,可以在" dbtable"中使用SQL查询代替表名,文档中的描述: https://spark.apache.org/docs/latest/sql-programming-guide.html
在查询"其中"例如,可以使用服务器特定功能来指定条件,以限制行数(例如" rownum"在Oracle中)。
答案 2 :(得分:0)
我没有对此进行过测试,但您应该尝试使用limit
代替take
。 take
在封面下调用head
,其中包含以下注释:
只有在期望得到的数组时才应使用此方法 因为所有数据都被加载到驱动程序的内存中,所以数据很小。
而limit
导致LIMIT被推入sql查询,因为它是一个懒惰的评估:
此函数与
head
之间的区别在于head
是一个操作并返回一个数组(通过触发查询执行),而limit
返回一个新的数据集。
如果您想要数据而不先将其拉入,那么您甚至可以执行以下操作:
...load.limit(limitNum).take(limitNum)