RowGroup
如果采用HDFS文件系统,影响Parquet文件读写性能的参数主要有两个,dfs.blocksize和parquet.block.size
- dfs.blocksize: 控制HDFS file中每个block的大小,该参数主要影响计算任务的并行度,例如在spark中,一个map操作的默认分区数=(输入文件的大小/dfs.block.size)*输入的文件数(分区数等于该操作产生的任务数),如果dfs.block.size设置过大或过小,都会导致生成的Task数量不合理,因此应根据实际计算所涉及的输入文件大小以及executor数量决定何时的值
- parquet.block.size 控制parquet的Row Group大小,一般情况下较大的值可以组织更大的连续存储的Column Chunk,有利于提升I/O性能,但上面也提到Row group是数据读写时候的缓存单元,每个需要读写的parquet文件都需要在内存中占据Row Group size设置的内存空间(读取的情况,由于可能跳过部分列,占据的内存会小于Row Group size),这样更大的Row Group size意味着更多的内存开销。同时设置该值时还需要考虑dfs.blocksize的值,尽量让Row Group size等同于HDFS一个block的大小,因为单个Row Group必须在一个计算任务中被处理,如果一个Row Group跨越了多个hdfs block可能会导致额外的远程数据读取。一般推荐的参数一个Row group大小1G,一个HDFS块大小1G,一个HDFS文件只含有一个块。
spark/sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala
val FILES_MAX_PARTITION_BYTES = buildConf("spark.sql.files.maxPartitionBytes")
.doc("The maximum number of bytes to pack into a single partition when reading files. " +
"This configuration is effective only when using file-based sources such as Parquet, JSON " +
"and ORC.")
.version("2.0.0")
.bytesConf(ByteUnit.BYTE)
.createWithDefaultString("128MB") // parquet.block.size