SparkSQL:如何在从数据库加载数据集时指定分区列

Posted

技术标签:

【中文标题】SparkSQL:如何在从数据库加载数据集时指定分区列【英文标题】:SparkSQL : How to specify partitioning column while loading dataset from database 【发布时间】:2018-12-26 06:10:18 【问题描述】:

我正在使用 Spark 2.3,并使用 jdbc 从 mysql 加载数据,如下所示

  val dataSet:Dataset[Row] = _spark
    .read
    .format("jdbc")
    .options(Map("url" -> jdbcUrl
                ,"user" -> username
                ,"password" -> password
                ,"dbtable" -> dataSourceTableName
                ,"driver" -> driver
                ))
    .load() 

我想根据表中的特定列对数据集进行分区。 我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

您需要指定partitionColumnupperBoundlowerBoundnumPartitions 选项。

这些在JDBC documentation for spark sql 的属性表中进行了描述。

如果指定了其中任何一个选项,则必须全部指定这些选项。在 此外,必须指定numPartitions。他们描述了如何 从多个工作人员并行读取时对表进行分区。 partitionColumn 必须是来自 有问题的表。请注意,lowerBoundupperBound 仅被使用 决定分区步长,而不是过滤表中的行。 所以表中的所有行都会被分区并返回。这个选项 仅适用于阅读。

有关upperBoundlowerBound 参数的进一步说明,请参见@PIYUSH PASARI 的answer。

他给出了以下使用以下参数值生成的查询示例

upperBound = 500lowerBound = 0numPartitions = 5

SELECT * FROM table WHERE partitionColumn < 100 or partitionColumn is null
SELECT * FROM table WHERE partitionColumn >= 100 AND <200 
SELECT * FROM table WHERE partitionColumn >= 200 AND <300
SELECT * FROM table WHERE partitionColumn >= 300 AND <400
...
SELECT * FROM table WHERE partitionColumn >= 400

这可以从JDBCRelation.scala中的代码看出。

如您所见,所有行都已获取,但如果您的上限和下限未覆盖整个数据范围,则第一个和最后一个分区可能比其他分区大。如果您不能确定上限和下限,想要偶数分区并且不关心获取每一行,您可以始终将上限和下限设置为 dbtable 参数中的条件。

【讨论】:

谢谢,有没有办法避免给出“upperBound and lowerBound”而只给出partitionColumn 不必指定每个参数。它们仅用于指定每个分区的步长。将返回所有行,但如果您的边界不正确,则第一个和最后一个分区可能大于其余分区。如果想要偶数分区并且只想要给定范围内的结果,您还应该在查询中设置上限和下限。【参考方案2】:
spark.read("jdbc")
  .option("url", url)
  .option("dbtable", "pets")
  .option("user", user)
  .option("password", password)
  .option("numPartitions", 10)
  .option("partitionColumn", "owner_id")
  .option("lowerBound", 1)
  .option("upperBound", 10000)

阅读以下链接了解更多

https://medium.com/@radek.strnad/tips-for-using-jdbc-in-apache-spark-sql-396ea7b2e3d3

http://spark.apache.org/docs/latest/sql-data-sources-jdbc.html

【讨论】:

以上是关于SparkSQL:如何在从数据库加载数据集时指定分区列的主要内容,如果未能解决你的问题,请参考以下文章

在 Keras 中加载数据集时如何修复错误?

滚动大型数据集时,PyQt QTableView 速度非常慢

当 Relay 游标分页总是获取整个数据集时,它如何处理大数据集?

如何在从 .Include 实体框架查询返回的数据上指定 where 子句?

每次firebase实时数据库数据集时,RecyclerView都会重新加载

转储数据集时将数据从 Hive 加载到 Pig 错误