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

时间:2018-12-26 06:10:19

标签: apache-spark apache-spark-sql

我正在使用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() 

我想基于表中的特定列对数据集进行分区。 我该如何实现?

2 个答案:

答案 0 :(得分: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参数中将上限和下限设置为条件。

答案 1 :(得分:1)

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)

有关以下链接的更多信息