Spark SQL如何决定从Hive表加载数据时将使用的分区数?

时间:2017-05-19 04:24:35

标签: apache-spark-sql

此问题与Number of partitions of a spark dataframe created by reading the data from Hive table

相同

但我认为这个问题得不到正确答案。请注意,问题是当使用SparkSession.sql方法对HIVE表执行sql查询而创建数据帧时,将询问将创建多少个分区。

IIUC,上面的问题不同于在创建数据帧时会创建多少分区,因为执行了一些像spark.read.json("examples/src/main/resources/people.json")这样直接从文件系统加载数据的代码 - 可能是HDFS。我认为后一个问题的答案由spark.sql.files.maxPartitionBytes

给出
  

spark.sql.files.maxPartitionBytes 134217728(128 MB)最大值   读取文件时要打包到单个分区的字节数。

实验上,我尝试从HIVE表创建一个数据框,total data in hive table / spark.sql.files.maxPartitionBytes

没有解释我得到的分区数量

同时添加到OP,最好知道如何控制分区的数量,即当人们想要强制使用与默认情况下不同的数字时使用火花。

参考文献:

https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/SparkSession.scala

https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/Dataset.scala

1 个答案:

答案 0 :(得分:8)

TL; DR:从Hive读取数据时的默认分区数将由HDFS blockSize控制。通过将mapreduce.job.maps设置为适当的值可以增加分区数,可以通过将mapreduce.input.fileinputformat.split.minsize设置为适当的值来减少分区数

从hive表加载数据时,Spark SQL会创建HadoopRDD的实例。

  

RDD,提供读取存储的数据的核心功能   Hadoop(例如,HDFS中的文件,HBase中的文件或S3),使用旧版本   MapReduce API(org.apache.hadoop.mapred)。

enter image description here

HadoopRDD依次根据org.apache.hadoop.mapreduce.lib.input.FileInputFormat(新API)和org.apache.hadoop.mapred.FileInputFormat(旧API)中定义的computeSplitSize方法拆分输入文件。

新API:

protected long computeSplitSize(long blockSize, long minSize,
                                  long maxSize) {
    return Math.max(minSize, Math.min(maxSize, blockSize));
  }

旧API:

protected long computeSplitSize(long goalSize, long minSize,
                                       long blockSize) {
    return Math.max(minSize, Math.min(goalSize, blockSize));
  }

computeSplitSize根据HDFS blockSize拆分文件,但如果blockSize小于minSize或大于maxSize,那么它将被限制在那些极端。 HDFS blockSize可以从

获得
hdfs getconf -confKey dfs.blocksize

根据Hadoop最终指南表8.5,minSize是从mapreduce.input.fileinputformat.split.minsize获得的,maxSize是从mapreduce.input.fileinputformat.split.maxsize获得的。

enter image description here

但是,该书还提到mapreduce.input.fileinputformat.split.maxsize

  

此属性不存在   在旧的MapReduce API中(除了   CombineFileInputFormat)。相反,它是间接计算的   作业总输入的大小除以指南编号   mapreduce.job.maps(或setNumMapTasks()指定的map任务   JobConf上的方法。

this post还使用总输入大小除以map任务数来计算maxSize。