【小文件那些事(二)】针对不同阶段下的小文件过多问题如何处理,最佳治理手段(星环Compact机制)

友情链接

如何判断小文件是否过多?

通常,空文件以及小于10M的文件可以判断为小文件,那么判断小文件是否过多可参考下方方式:

① 查看单表的小文件个数,一般小文件超过1000个即可判断为小文件过多;

② 对于text/orc/torc表,可以通过星环的巡检工具巡检,并下载巡检报告,查看表的小文件数据量和占比;

image.png

③ 对于holodesk表,通过DBA页面查看:登录DBA,依次选择:存储-->数据库-->统计--> holodesk,可以查看单表的小文件个数,进而判断小文件是否过多。

image.png


小文件过多如何解决、治理方法

因此,小文件是特别常见的现象,解决小文件问题迫在眉睫!!!一般来说,一个任务是由几个步骤组成的,而小文件的产生也来自任务的各个流程和步骤:

上游 => 本地文件系统 => HDFS => Map => Reduce => FileSink

所以解决小文件问题就是需要从最前面的步骤中入手。而且解决小文件的隐患,肯定也是越早越好,就像过滤下推,能尽早做的过滤条件一定是尽早过滤。

因此,能在本地文件系统解决的问题,没必要放到HDFS上解决。就像前面章节的内容所述,HDFS本身就不适合存储大量小文件,小文件过多会导致namenode元数据特别大, 占用太多内存,严重影响HDFS的性能。

当前治理小文件的现有手段主要有以下几种:

1)SQL端规范

但归根结底,治理小文件的最优解一定是从源头(集群规划设计和搭建)开始就进行规范管理。比如在表结构和SQL语句方面进行规范,特别是分桶个数,分区类型的选择,范围分区跨度的选择。如果从初期就开始重视,确保不会出现小文件过多以及合并完成后还是小文件的问题,可以最大程度的减少后续因该问题引发的集群异常和宕机的可能,进一步达到治理小文件的目的。

SQL端规范适用于以下原因导致的小文件治理:

  • 表结构不合理,设置分桶数过大,数据平均分布,小文件过多;
  • 分桶字段不合理,导致数据倾斜,产生大量小文件;
  • 单值分区设置不合理,导致单分区数据量小,产生大量小文件;

表结构

分桶表

分桶表表结构创建之前需要对表的数据分布情况进行大致的分析,一般遵循的原则为,选择离散度高的字段进行分桶,避免选择decimal类型的字段做为分桶键,一般选择表的主键等字段。包括账号,客户号,证件号码等。分桶个数选择非31的质数,分桶字段选择时,注意尽量使记录分布均匀,以避免数据倾斜,设计表结构时首先要预估该表的数据量和数据文件的大小,按照每个桶文件100-200M的大小来设置分桶个数。

另外,在考虑分桶个数的时候,同时要考虑是否已经分过区。对于已经分过区的表,要按照单分区的大小进行桶数的估计,而不是依照原始表。

分区表

建议创建范围分区表,不推荐使用二级分区,分区字段选择上一般选择时间,区域等字段,并根据数据的每天和每月增量的大小来界定每个分区的范围。如果一个分区数据量太大,可以考虑创建分区分桶表,并合理的设置分桶键和分桶个数。

另外,在考虑分桶个数的时候,要考虑单分区的大小,要按照单分区的大小进行桶数的估计,而不是依照原始表。

不规范表结构改造

对于由于表结构原因导致小文件过多的表,建议是重建表结构,一般具体流程为:备份表和数据-->重建表结构-->回填表数据-->验证表数据和文件-->删除备份表。

注意:对于分区表、分桶表、分区分桶表,回填数据时,可以sort by备份表的分区键、分桶键来提升表的查询效率。

SQL语句规范

① 必须尽量避免大表与大表直接JOIN,执行之前要检查分析一下SQL,如果有小表,先用小表或是过滤率较高的表过滤大表,即尽可能先做与小表有关的 JOIN,再使大表参与进来;

② 大表与小表JOIN 时,可以采用MapJoin,减少Shuffle过程;

③ 两张大表关联时,使用 Bucketed Join;

④ 小表 Join 大表时,使用 Lookup Join;;

⑤ 数据倾斜导致 Join 性能地下时,使用 SKEWJOIN;


SkewJoin是星环针对大表与大表之间进行关联发布新功能,社区版中也有引入,可以在一定程度缓解大表关联场景下的数据倾斜问题,介绍及使用教程可查看: SkewJoin使用方法及原理介绍

⑥ 注意笛卡尔积等数据翻倍情况的出现;

⑦ 减少INNER JOIN的中间量,在多表进行连接时,JOIN之间的连接顺序将极大影响SQL的执行效率。应尽量优先执行过滤高的JOIN,以提高SQL的整体执行速度;

⑧ 先INNER JOIN后OUTER JOIN,当一条语句中的INNER JOIN与OUTER JOIN顺序执行且关联,并都涉及同一张表时,执行顺序通常也可满足交换律。一般情况下,由于带过滤条件的INNER JOIN会减少记录数,而OUTER JOIN不会减少记录数,所以建议用户先执行INNER JOIN;

⑨ 添加手工推导的过滤规则,即在原有SQL的基础上手动的添加额外的过滤条件,这些过滤条件仅仅以优化为目的,不会影响查询返回结果。它们是通过表与表之间的关系推导得到的,是以正确分析两表或多表之间存在的关联信息为前提的,最重要的是能够根据一张表的结果锁定结果所在范围;

⑩ 用GROUP BY实现DISTINCT,在DISTINCT可以用GROUP BY去重表达时,尽量用GROUP BY;

⑪ 尽量返回更少的数据。在编写SQL语句时,通过明确指定查询字段去除不必要的返回字段,以减少不必要的查询时间;

⑫ 多表关联时,使用SQL92标准写法,目的是更能体现表与表之间的关联关系,杜绝使用 Right 连接、非SQL92标准的"(+)左连接";

⑬ 如果业务逻辑允许的情况下,尽量用UNION ALL代替UNION,用UNION ALL代替OR;

⑭ SQL语句的WHERE子句中应尽可能将字段放在等式左边,将计算操作放在等式的右边;

⑮ SQL语句的操作符两边类型应相同,禁止潜在的数据类型转换,建议用户在执行计算前通过类型转换,使各操作数的类型匹配,或者建表时尽可能的把字段安排成相同的数据类型。

2)存储端合并

存储端合并主要是合并已经写入到存储的文件,当表中有小文件或者小文件过多时,可以使用存储端合并的方式来治理小文件。存储端合并的方式主要适用于以下原因导致的小文件问题:

  • 频繁的写入数据;
  • torc表compact多次合并失败后进入黑名单,导致小文件不再继续合并;
  • 历史数据流程导致小文件问题,这些数据一般是从别的数据库迁移过来,后续没有进行治理;

需要注意的是,不同的表格式的合并方式不同。

a. Torc事务表/Holodesk表

针对Torc及Holodesk表星环均提供了Compact机制,用户可以根据业务特点来设置一些参数自定义小文件的自动合并策略以平衡小文件数量和合并开销,比如设置定期合并策略或者设置触发阈值等。

除此之外,针对Holodesk表用户可以使用星环新推出的Compact Service(小文件合并专用服务)进行小文件合并任务。常见的小文件合并功能是通过计算引擎服务来执行 Compact 任务的,可能会占用部分计算资源。新推出的Compact Service则在组件级别做了隔离,开启后不会影响到Quark的查询计算性能,合并效果更好。

除了上述的自动合并机制之外,用户也可以通过在星环运维管理平台DBA Service查看当前的小文件数量,管理Compact任务,如果检查发现小文件数量过多,可以通过同步或异步的方式手动执行小文件合并任务,减少小文件数量。

由于篇幅原因,更多内容详见:

b. Orc表/Text表

对于holodesk及torc表用户可以采用自动或手动的形式进行合并,或者使用最新的Compact Service,但是针对text及orc非事务表来说,一直以来没有一个很完美的合并方法,这是因为非事务表不像事务表有文件合并的逻辑。

开源方案中的合并思路是根据每一张表的数据量和分布情况,手动编写任务进行重写来实现小文件合并的效果,在这个过程中,表只能读不能写,表相关业务会受到影响,而且由于合并处理的滞后性,无法及时清理小文件,进而导致各种风险,如GC等;

因此,星环Galactus应运而生!!

Galactus可以自动检测到小文件自动合并掉,用户无需担心因为处理不及时或有疏漏影响到业务系统,更加贴合生产上的需求。

小文件合并功能在数据管理和处理中具有重要性,尤其在分布式存储和计算系统中更为显著。除了可以预防问题的产生之外,使用Galactus还具有以下好处:

  • 减少存储开销:小文件占用磁盘存储时,会导致存储资源的碎片化,浪费磁盘空间。通过合并小文件,可以减少存储开销,提高存储资源的利用率;
  • 提升数据访问效率:大量小文件会增加文件系统的元数据开销,降低文件系统的性能。合并小文件可以充分提升数据的访问效率,降低寻址时长;
  • 提高数据传输效率:在网络传输中,大文件通常比小文件更有效率。小文件合并后形成的大文件,可以减少传输过程中的网络开销,提高数据传输效率,尤其对于需要跨网络传输的场景,如分布式计算场景中的数据传输;
  • 优化计算性能:在分布式计算环境中,大量小文件可能导致任务调度和执行的开销增加。小文件合并后可以减少任务调度和执行的时间,减少系统开销,从而提高整体的计算性能,处理效率;
  • 降低文件系统负载:大量小文件可能导致文件系统的负载增加,从而影响整个系统的性能。通过合并小文件可以降低文件系统的负载,进一步提高系统的稳定性和可靠性;

总体而言,小文件合并功能对于优化存储资源、提高数据访问效率、降低网络传输开销以及优化计算性能都起着重要作用,特别是在大规模数据处理和分布式环境中。因此,Galactus至关重要!!

由于篇幅原因,更多客户应用案例及使用Demo内容详见: Text/ORC非事务表合并最佳方式

c. 归档分区

除了针对上述表实现的合并机制外,TDH以及星环分布式分析型数据库ArgoDB在6.0及后续版本中引入了归档分区的功能,用户可以跨分区进行合并。归档分区的实现手段是用范围分区去表示单值分区,适用于分区字段为离散类型的单值分区,如日期 (暂不支持时间戳类型)、整数的场景。

通过分区归档合并功能,可以将大量小文件(归档前的单值分区)合并成较大的文件(归档后的范围分区),从而减少存储开销、元数据管理的开销以及处理时的任务调度开销。

由于篇幅原因,更多使用方法可参考: 归档分区功能使用方法

3)计算端合并

计算端合并分为两个阶段:map端合并和reduce端合并,适用于以下原因导致的小文件问题:

  • 不规范的sql语句,导致的小文件;

正如前面所说,小文件的产生来自任务的各个流程和步骤,越早解决对业务的影响越小。如果在前期无法解决的情况下,可以考虑在以下两个阶段进行合并:

a. maptask阶段合并

Maptask阶段合并可以使用automerge功能,在map端控制map task的数目,它可以根据每个partition (数据块) 所在的位置及大小将多个partitions交给一个task去完成;

在星环TDH9.3及后续版本中,产品引入了改进后的automergeV2功能,V2版本在性能方面有很大提升,并且解决了有关automerge可能存在的一些问题。

由于篇幅原因,有关automerge功能及优化后的automergeV2功能如何使用,情参考:Automerge及优化后的AutomergeV2用法及注意事项

b. reduce 阶段合并:

当小文件过多引起后续reduce任务数量暴增到一定值的情况下,引擎出于自我保护会中断任务并返回一些报错提醒,因此可以设置合理的reduce个数(mapred.reduce.tasks),以保证单reduce处理合适的数据量。

设置mapred.reduce.tasks数可以增加初始化性能,建议 500w数据量设置一个tasks。同时也可以按照文件的大小来设置tasks数据,如果小于500M,则设置为5,如果大于500M,则是文件大小/300M设置,根据hdfs上文件总大小合理控制。也可以将reduce数设定为集群vcore的一半,既保证vcore被充分利用,又不影响其他程序的工作。但是最终的mapred.reduce.tasks尽量小于1000。


评论
登录后可评论
发布者
星小环分享号
文章
180
问答
205
关注者
27
banner
关注星环科技
获取最新活动资讯

加入TDH社区版技术交流群

获取更多技术支持 ->

扫描二维码,立即加入