在ORC文件合并时,容器因OOM而被杀死

时间:2019-08-02 08:20:06

标签: hadoop hive bigdata orc

我有一个hadoop作业,可以合并表中不同分区的不同存储桶文件。 例如:我有一个表,该表按create_date分区,并有12个存储桶。

@Configuration
class DataSourceConfig {
    public final static int SPAIN = 2;
    public final static int BRAZIL = 1;

    @Bean
    @Qualifier("dataSources")
    public Map<Integer, DataSource> dataSources() {
        Map<Integer, DataSource> ds = new HashMap<>();
        ds.put(SPAIN, buildSpainDataSource());
        ds.put(BRAZIL, buildBrazilDataSource());
        return ds;
    }

    private DataSource buildSpainDataSource() {
        ...
    }

    private DataSource buildBrazilDataSource() {
        ...
    }

}

@Service
class MyService {
    @Autowired
    @Qualifier("dataSources")
    Map<Integer, DataSource> dataSources;

    Map<String, Object> getObjectForCountry(int country) {
        NamedParameterJdbcTemplate t = new NamedParameterJdbcTemplate(dataSources.get(country));
        return t.queryForMap("select value from mytable", new HashMap<>());
    }
}

所以说我有12个create_date分区。 当我运行Hadoop作业(这是仅地图作业,不涉及reducer)时,它将从每个分区中选择具有相同名称的存储桶文件,将它们合并为一个文件,并将其存储在新分区中。

create_date='2019-10-01' will have 4 bucket files, viz., part00000_0, part00000_1, part00000_2, part00000_3,........,part00000_11
create_date='2019-10-02' will have 4 bucket files, viz., part00000_0, part00000_1, part00000_2, part00000_3,........,part00000_11

因此,将在我的应用程序中启动12个mapper作业进行合并(每个mapper处理12个文件)。 我的工作的默认映射器内存(mapreduce.map.memory.mb)为2.5G 但是在执行此操作时,在大多数情况下会出现以下错误:

For eg:
merge(create_date='2019-10-01'/part00000_0, create_date='2019-10-02'/part00000_0, 
create_date='2019-10-03'/part00000_0,.....,create_date='2019-10-12'/part00000_0) 
into 
merge_partition/part00000_0

Similarly:
merge(create_date='2019-10-01'/part00000_1, create_date='2019-10-02'/part00000_1, 
create_date='2019-10-03'/part00000_1,.....,create_date='2019-10-12'/part00000_1) 
into 
merge_partition/part00000_1

我通过了ORC代码,发现: https://github.com/apache/orc/blob/master/java/core/src/java/org/apache/orc/impl/RecordReaderImpl.java。 readStripe()方法在读取条带时将整个条带拉入内存。

因此,如果考虑到这一点,我将对12个part00000_x文件执行合并操作,并且我的ORC条带大小为256 MB。 因此12x256 MB = 3072MB。这超出了我的容器限制。 我做了一个小的POC来确认这一点,然后签出。 另外,我确认文件的大小无关紧要。即使文件大小为1G,也要占用256MB的堆空间;对于文件大小为4.5G的文件,它也要占用相同的堆空间。 因此,我想到添加一个简单的代码,该代码将根据表的分区数量来增加映射器的内存。

但是我发现生产中很少有大约200多个分区(=要合并的文件数量)的作业,并且运行良好。按照我的POC的说法,它们应该占用超过50G的映射器内存才能成功,但是在使用10G的映射器内存时它们可以正常运行。

有人可以提供有关解决此问题的宝贵建议。

0 个答案:

没有答案