因SHUFFLE的KEY不同对落盘文件的影响

业务背景

在建立数仓体系过程中,采用ORC+SNAPPY存储,单分区文件大小TB级别,对比前后依赖表以及同样体量的表,只有GB级别,故对这种情况产生怀疑,进行验证

        验证一、确定数据量、以及具体字段数据正常

        验证二、只有触发shuffle就会造成文件大小异常,在不触发shuffle的情况下,不会出现

        验证三、SPARK、HIVE引擎都有实验,都会出现

故开始具体问题定位,以及解决方案确认

涉及过程

SPARK执行过程中主要通过left join或者DISTRIBUTE BY 触发的shuffle

SPARK JOIN策略

        Sort Merge Join

  • spark默认的,两张大表进行join时候使用,小表不进行配置Broadcast也会触发
    • 主要包括三个阶段:
      • Shuffle 阶段:两张大表根据Join key进行Shuffle重分区
      • Sort 阶段: 每个分区内的数据进行排序
      • Merge 阶段: 对来自不同表的排序好的分区数据进行JOIN,通过遍历元素,连接具有相同Join key值的行来合并数据集
    • 参数:spark.sql.join.prefersortmergeJoin

        Broadcast Hash Join

  • 当有一张表比较小的时候可以使用,比如事实表和维表进行join,可以提高join的效率
    • 主要包括两个阶段:
      • broadcast阶段:将小表广播分发到大表所在的所有主机。涉及到不同的广播算法
      • hash join阶段:在每个executor上执行单机版hash join,小表映射,大表试探。
    • 参数:spark.sql.autoBroadcastJoinThreshold

        ·Shuffle Hash Join

  • 当要JOIN的表数据量比较大时使用,可以将大表按照JOIN的key进行重分区,保证每个相同的JOIN key都发送到同一个分区中
    • 大表和大表join的情况下,Shuffle Hash Join和Sort Merge Join哪个效率更高?
    • 主要包括两个阶段:
      • shuffle阶段:分别将两个表按照join key进行分区,将相同join key的记录重分布到同一节点,两张表的数据会被重分布到集群中所有节点
      • hash join阶段:每个分区节点上的数据单独执行单机hash join算法。 

        Cartesian Join

  • 两张表在join的时候没有join key可以使用

        Broadcast Nested Loop Join

  • 没有其他的更好的方式可以使用

SQL的四种排序

        order by、sort by、distribute by、cluster by

  • order by:对输入做全局排序,因此只有一个reducer(多个reducer无法保证全局有序),只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。会提升压缩,可以实现较小存储。
  • sort by:局部排序,其在数据进入reducer前完成排序。Sort by 为每个reducer 产生一个排序文件。
  • distribute by:按照指定的字段对数据进行划分输出到不同的reducer中。控制某个特定行应该到哪个reducer。可以解决小文件问题,触发shuffle的执行。
  • cluster by:除具有distribute by功能外还具有sort by的功能。但是排序只能是升序。实现分桶管理,提高查询效率,也会提升压缩。

存储格式

Text,Sequence,RCfile,ORC,Parquet,AVRO

  • Text:可读性好,占用磁盘空间大(文本 行式存储),使用但是不常用
  • Sequence:Hadoop API提供的一种二进制文件,以key,value的形式序列化带文件中(二进制 行式存储)
  • RCfile:面向列的存储格式(二进制 列式存储,压缩)
  • ORC:RCfile的升级版,优化了压缩、查询(二进制列式存储,压缩),文件可切分,支持复杂的数据结构,常用的压缩格式Lzip,Snappy,压缩、解压一般是冲突的在
  • Parquet:存储嵌套式数据,如json;支持更多编码;可以很sparkSQL很好的结合。列式存储高压缩(二进制列式存储,高压缩)压缩和查询性能比ORC稍差

ORC的数据存储方式

        ORC存储过程中,记录会被横向切分成多个stripes,每个stripes内的数据以列为单位进行存储,所有列的内容保存在同一个文件中,通过配置对block压缩,设置HDFS的每个block存储ORC文件的一个stripe

结论与建议

        故在触发shuffle的过程中因key的不同,例如单个字段做key的重复率会更高、多个字段做key的重复率会降低。shuffle根据不同的key进行分发,ORC又是对block压缩,将相同的数据压缩,单个文件重复数据降低导致压缩比降低,单分区文件大小相比其他文件异常。

        解决:通过cluster by或者sort by进行数据分发,重新触发shuffle,提高压缩

你可能感兴趣的:(Spark,spark,大数据,hive)