ORC文件stripeSize引发的一起血案

举报
人在江湖飘飘 发表于 2020/05/27 20:09:26 2020/05/27
【摘要】 orc文件stripeSize过小,大文件拷贝OOM

1. 背景

    对hive做数据更新,由于不支持事务,所以需要先对原表进行数据备份,即存到另外一张表结构一样的hive表中,其中hive表数据存储格式为ORC。

2. ORC文件结构介绍

  • ORC的全称是(Optimized Row Columnar),ORC文件格式是一种Hadoop生态圈中的列式存储格式,主要作用是降低文件系统的存储空间和加速查询。

  • 文件结构:

  1. ORC FILE包含了一组组的行数据,被称作为stripes,此外还包含其他file footer等额外信息。

  2. ORC FILE的最后还包含一个postscript区域,该区域主要用来存储压缩参数以及压缩页脚的大小。

  3. 在默认情况下,一个stripe的大小为250MB。大尺寸的stripes使得从HDFS读数据更高效。

  •   文件结构简略图

3. 案发现场

    通过spark sql拷贝hive表数据到另外一张相同表结构的hive表中,配置很大的资源仍然很快oom。

    hive表的数据存储格式为orcfile,其中,hive表的数据为8亿条左右,orc文件为54.6G,实际大小大概为400G。

    日志表现:JVM内存年轻代和老年代都被占满,触发FULL GC,通过使用测试时候测试的相同数据量的资源配置仍然无法解决FULL GC问题。

    

  • 疑问:为什么测试阶段,针对相同数据量,相同资源配置,作业能成功,到现网环境就不行,到底有什么差别?


  • 通过jmap命令

    执行命令:jmap -dump:format=b,file=/tmp/pid.dump pid,通过获取dump文件,可以离线分析作业运行时jvm堆内存,检查内存泄漏,检查严重影响性能的大对象,各种对象所占用的内存大小等。

  • dump文件日志分析图如下所示:


        分析dump文件找出占用超大堆内存的具体原因,metadata中的stripeStats占用的堆内存巨大,通过ORC文件的结构可以得出,orc文件的stripe数量过多,导致读取orc文件时的metadata占用超大内存。

  • 为什么该文件的stripe数量会如此之大?

        结合现网环境排查出测试环境和现网环境的差异:测试数据是由很多128M的文件构成,现网数据则是由CDM生成的一个大文件,直接以orc的格式存储到了hdfs文件系统中,导致在做数据备份的时候,spark读取的是整个大文件,通过分析CDM代码,得出原因:stripeSize大小是固定的,针对大文件就会生成很多的stripes。

代码分析:

其实,我们根据堆栈异常也可以验证是hive在读取orc文件,初始化Metadata的时候,会以stripe为单位进行元数据的统计,如下异常所示:


4. 结论

        orc文件本身的大小并不会真正影响读取数据时metadata的大小,真正影响的是stripe的数量,合理设置stripSize才是王道,stripSize可以设置为可配置项,才能以变应变。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。