繁体   English   中英

spark、scala 和 jdbc - 如何限制记录数

[英]spark, scala & jdbc - how to limit number of records

有没有办法限制使用 spark sql 2.2.0 从 jdbc 源获取的记录数?

我正在处理将 > 200M 的大量记录从一个 MS Sql Server 表移动(和转换)到另一个表的任务:

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 来实现我的目标。

要限制下载的行数,可以使用 SQL 查询代替“dbtable”中的表名。 文档中的说明。

在查询中可以指定“where”条件,例如,使用服务器特定的功能来限制行数(如 Oracle 中的“rownum”)。

这种方法对关系数据库有点不利。 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 格式保存在本地计算机中,这是您可以使用任何语言进行探索的最常见格式。 每次你想加载它时,从这个文件中获取这些数据。 如果您想要实时分析,或任何其他类似的东西。 我建议您使用数据转换构建一个管道以更新另一个存储。 每次都使用这种方法来处理从数据库加载的数据并不好。

我没有测试过这个,但你应该尝试使用limit而不是take take电话head具有下列注意事项在幕后:

仅当预期结果数组较小时才应使用此方法,因为所有数据都已加载到驱动程序的内存中。

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

这个函数和head的区别在于head是一个 action 并返回一个数组(通过触发查询执行),而limit返回一个新的 Dataset。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM