You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark SQL读取Hive表时,原表与新表分区数为何不一致?

为啥读取原Hive表和新写入表的分区数不一样?

嘿,这个问题我之前也碰到过,其实核心是Spark读取和写入Hive表时的分区逻辑不是完全对应的,我给你拆解下可能的原因:

1. 存储格式差异导致文件大小变化

你写入新表时用的是Parquet格式,但原表src_table可能是其他格式(比如TextFile、ORC)。不同格式的压缩率、存储结构差异很大:

  • 比如TextFile是行式存储,压缩率低,文件体积大;Parquet是列式存储,压缩率高,相同数据的文件体积会小很多。
  • Spark读取表时的分区数,是结合HDFS BlockSize和实际文件大小来计算的:一个大于BlockSize的文件会被拆分成多个分区,小文件则可能被合并。当新表的文件大小和原表差异明显时,读取时的分区数自然就不一样了。

2. Spark写入时的配置影响了输出文件数

Spark写入数据时,有几个配置会直接影响生成的文件数量,进而影响后续读取的分区数:

  • spark.sql.files.maxRecordsPerFile:限制每个输出文件的最大记录数,如果原DataFrame的一个分区记录数超过这个值,会被拆分成多个文件,导致新表的文件数变多。
  • spark.sql.adaptive.enabled:如果开启了自适应执行,Spark会在写入时自动合并小分区,减少输出文件数,这会让新表的文件数比原DataFrame的分区数少。
  • spark.sql.shuffle.partitions:如果你的写入操作涉及 shuffle(比如有聚合、排序),这个配置会决定 shuffle 后的分区数,不过你这里是直接写数据,大概率不涉及,但也可以留意下。

3. 原表是分区表,写入时未保留分区结构

如果src_table是Hive分区表(比如按日期、地域分区),你用select *读取时,Spark会扫描所有分区下的文件,生成的分区数是所有分区文件合并/拆分后的数量。但你写入new_table时没有用partitionBy指定分区,新表会变成无分区表,所有数据会被写入到同一个目录下,生成的文件数和原表的分区文件数逻辑完全不同,读取时的分区数自然就不一样了。

4. 小文件合并策略的差异

如果原表存在大量小文件,Spark读取时会通过spark.sql.files.maxPartitionBytes(默认128MB)自动合并小文件,生成较少的分区。但你写入新表时,如果没有开启小文件合并,会按原DataFrame的分区数生成文件,这些文件可能还是小文件;后续读取新表时,如果合并策略不同(比如配置了不同的maxPartitionBytes),就会生成和原表不同的分区数。

怎么让分区数一致?

如果你希望读取新表时的分区数和原表一致,可以试试这些方法:

  • 写入前手动指定分区数:
    newData.repartition(data.rdd.getNumPartitions)
           .write.mode("overwrite").format("parquet").saveAsTable("new_table")
    
  • 调整读取配置,让两次读取的合并策略一致:比如把spark.sql.files.maxPartitionBytes设置成相同的值,确保小文件合并逻辑一样。
  • 如果原表是分区表,写入新表时用partitionBy保留相同的分区字段,让存储结构和原表一致。

内容的提问来源于stack exchange,提问作者cat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:54:42