【问题标题】:What is the meaning of partitionColumn, lowerBound, upperBound, numPartitions parameters?partitionColumn、lowerBound、upperBound、numPartitions参数是什么意思?
【发布时间】:2017-04-26 09:32:02
【问题描述】:

在 Spark 中通过 JDBC 连接从 SQL Server 获取数据时,我发现我可以设置一些并行化参数,例如 partitionColumnlowerBoundupperBoundnumPartitions。我已经通过spark documentation 但无法理解它。

谁能解释一下这些参数的含义?

【问题讨论】:

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


    【解决方案1】:

    只想添加到经过验证的答案中,

    没有它们你会丢失一些数据是误导..

    从文档中, 请注意,lowerBound 和 upperBound 仅用于决定分区步长,而不用于过滤表中的行。所以表中的所有行都会被分区并返回。此选项仅适用于阅读。

    这意味着你的表有 1100 行,并且你指定

    lowerBound0

    upperBound1000 和

    numPartitions: 10 , 您不会丢失 1000 到 1100 行。您最终会得到一些分区的行数超过预期的结果。(步幅值为 100)。

    【讨论】:

    • 你知道 Spark 对剩下的 100 行做了什么吗?例如,这是否意味着您的 10 个分区将有 110 行?
    【解决方案2】:

    创建分区不会因为过滤而导致数据丢失。 upperBoundlowerboundnumPartitions 只是定义了如何创建分区。 upperBoundlowerbound 没有定义要获取的 partitionColumn 值的范围(过滤器)。

    For a given input of lowerBound (l), upperBound (u) and numPartitions (n) 
    The partitions are created as follows:
    
    stride, s= (u-l)/n
    
    **SELECT * FROM table WHERE partitionColumn < l+s or partitionColumn is null**
    SELECT * FROM table WHERE partitionColumn >= l+s AND <2s  
    SELECT * FROM table WHERE partitionColumn >= l+2s AND <3s
    ...
    **SELECT * FROM table WHERE partitionColumn >= l+(n-1)s**
    

    例如,对于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
    

    根据partitionColumn的实际取值范围,每个分区的结果大小会有所不同。

    【讨论】:

    • 您能否澄清您对partitionColumn 中的值的假设?如果您没有像 1、2、3、4、...这样的唯一整数 ROWID,我无法理解这是如何工作的。
    【解决方案3】:

    实际上,上面的列表遗漏了几件事,特别是第一个和最后一个查询。

    没有它们,您将丢失一些数据(lowerBound 之前的数据和upperBound 之后的数据)。从示例中不清楚,因为下限为 0。

    完整列表应该是:

    SELECT * FROM table WHERE partitionColumn < 100
    
    SELECT * FROM table WHERE partitionColumn BETWEEN 0 AND 100  
    SELECT * FROM table WHERE partitionColumn BETWEEN 100 AND 200  
    

    ...

    SELECT * FROM table WHERE partitionColumn > 9000
    

    【讨论】:

    • 这对于 JdbcRDD (see the code) 来说是 100% 准确的。特别是,如果您将upperBound 设置得太低,一个执行器将比其他执行器完成更多的工作,并且可能会耗尽内存。
    • 快速问题:什么类型的列最适合 PartitionBy ?顺序? UUID?
    • BETWEEN 运算符具有包容性:包括开始值和结束值。那么上面的sql会查询到重复数据吧?
    • 答案不准确,因为在某些数据库中BETWEEN 包含上下限。实际实现分别使用&gt;=&lt;Spark doc
    • 这个答案是否假设 partitionColumn 的值从 1 增加到 1000,例如?否则没有意义。我有一个由 Netezza 数据库分配的partitionColumn,它是一个很大的数字234235000234234999。如果upperBound 指的是元素的数量,而不是partitionColumn 中的值,那么这个答案对我来说没有意义。
    【解决方案4】:

    很简单:

    • partitionColumn 是用于确定分区的列。
    • lowerBoundupperBound 确定要获取的值的范围。完整的数据集将使用与以下查询对应的行:

      SELECT * FROM table WHERE partitionColumn BETWEEN lowerBound AND upperBound
      
    • numPartitions 确定要创建的分区数。在lowerBoundupperBound 之间的范围被划分为numPartitions,每个numPartitions 的步幅等于:

      upperBound / numPartitions - lowerBound / numPartitions
      

      例如,如果:

      • lowerBound: 0
      • upperBound: 1000
      • numPartitions: 10

      Stride 等于 100,分区对应于以下查询:

      • SELECT * FROM table WHERE partitionColumn BETWEEN 0 AND 100
      • SELECT * FROM table WHERE partitionColumn BETWEEN 100 AND 200
      • ...
      • SELECT * FROM table WHERE partitionColumn BETWEEN 900 AND 1000

    【讨论】:

    • 见安德烈的回答。第一个和最后一个 SELECT 在他的答案中是正确的,但在这个答案中不正确
    • Spark docs 中说:注意lowerBound 和upperBound 仅用于决定分区步长,而不是用于过滤表中的行。所以表中的所有行都会被分区并返回。此选项仅适用于读取。这意味着将获取整个表,而不仅仅是lowerBound和upperBound之间的部分。
    • 答案不准确,因为在某些数据库中BETWEEN 包含上下限。实际实现分别使用&gt;=&lt;Spark doc
    • 这个答案是完全错误的,这意味着上限和下限会过滤正在读取的数据集。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-07
    • 2016-10-17
    • 2015-03-05
    • 2014-05-31
    • 2012-09-16
    • 2020-12-16
    相关资源
    最近更新 更多