火花,斯卡拉& jdbc - 如何限制记录数

时间:2017-10-27 23:55:07

标签: sql scala apache-spark jdbc

有没有办法限制使用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实现我的目标。

3 个答案:

答案 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代替taketake在封面下调用head,其中包含以下注释:

  

只有在期望得到的数组时才应使用此方法   因为所有数据都被加载到驱动程序的内存中,所以数据很小。

limit导致LIMIT被推入sql查询,因为它是一个懒惰的评估:

  

此函数与head之间的区别在于head是一个操作并返回一个数组(通过触发查询执行),而limit返回一个新的数据集。

如果您想要数据而不先将其拉入,那么您甚至可以执行以下操作:

...load.limit(limitNum).take(limitNum)