【问题标题】:Spark JDBC fetchsize optionSpark JDBC fetchsize 选项
【发布时间】:2018-02-24 22:01:20
【问题描述】:

我目前有一个应用程序,它应该连接到不同类型的数据库,使用 Spark 的 JDBC 选项在该数据库上运行特定查询,然后将生成的 DataFrame 写入 HDFS。

Oracle 的性能非常糟糕(没有检查所有这些)。原来这是因为 fetchSize 属性默认为 10 行。所以我将它增加到 1000,性能提升非常明显。然后,我将其更改为 10000,但随后一些表开始因执行程序中的内存不足问题而失败(6 个执行程序,每个 4G 内存,2G 驱动程序内存)。

我的问题是:

  • Spark 的 JDBC 获取的数据是否在每次运行时都保存在执行程序内存中?有没有办法在作业运行时取消持久化它?

  • 从哪里可以获得有关fetchSize 属性的更多信息?我猜它不会被所有 JDBC 驱动程序支持。

  • 我是否需要注意与 JDBC 相关的其他事项以避免 OOM 错误?

【问题讨论】:

    标签: apache-spark jdbc apache-spark-sql


    【解决方案1】:

    Fetch Size 只是 JDBC PreparedStatement 的一个值。

    你可以在 JDBCRDD.scala 中看到它:

     stmt.setFetchSize(options.fetchSize)
    

    您可以阅读更多关于 JDBC FetchSize here

    您还可以改进的一件事是设置所有 4 个参数,这将导致读取并行化。查看更多here。那么你的阅读可以被拆分到多台机器上,所以每台机器的内存使用量可能会更小。

    有关支持哪些 JDBC 选项以及如何支持的详细信息,您必须搜索您的驱动程序文档 - 每个驱动程序都可能有自己的行为

    【讨论】:

    • 嘿,好的:D 我不喜欢这个来源的一件事是我们必须依赖第 3 方驱动程序——它们的工作方式都不同。但是谁不使用 RDBMS? ;)
    • 读取混乱(并行化,可能不一致,除非您锁定整个数据库)写入可能会使您在部分失败时处于不一致状态。我觉得COPY TO - COPY FROM 几乎总是一个更好的解决方案。
    • 谢谢。我相信这回答了我的问题。
    • @philantrovert 你是如何将这个fetchSize 属性传递给SparkDataFrameReader 的?我尝试在spark.read.jdbc(..) 方法的connectionProperties 参数中传递它,但它似乎对here 提到的性能没有任何影响。此外,该属性的确切键是什么:fetchsizefetchSizefetch_size?我正在使用MySQLSpark 2.2.0
    • 那么我是在connectionProperties 参数中传递DataFrameReader.jdbc(..) 方法还是通过DataFrameReader.option(..) 方法?当我使用标准的Connector/J 驱动程序时,它是否适用于MySQL
    【解决方案2】:

    要回答 @y2k-shubham 的后续问题“我是否在 connectionProperties 参数中传递它”,对于 the current docs,答案是“是”,但请注意小写的 's'。

    fetchsize JDBC 提取大小,它决定每次往返要提取多少行。这有助于在默认为低提取大小的 JDBC 驱动程序上提高性能(例如,具有 10 行的 Oracle)。此选项仅适用于阅读。

    【讨论】:

      猜你喜欢
      • 2019-05-06
      • 2016-12-16
      • 2021-06-24
      • 2014-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-15
      相关资源
      最近更新 更多