首先,发现这个问题是在执行一个非常简单的统计表数据量的sql时,发现耗时竟然需要一个多小时,而且该表数据量只有一亿四千万条左右
--该查询耗时一个多小时,但结果数据只有一亿多条,原因待调查
select count(0) from ads_ship_NodeException_data;
耗费时间如下
首先,先找一张差不多数据量的表执行相同的sql,排查是否为集群机器的问题,比如cpu、磁盘等,虽然这种可能性不是很大
--该表3个分区的数据量预估在一亿左右
select count(0) from dwd_dynamic_format_data
where dt = '2023-02-01' or dt = '2023-02-02' or dt = '2023-02-03';
查询结果为125431044条数据,和1亿四千万条差一点,但是执行时间只有30秒,两者差距太明显了
到这里排除了集群机器的问题,然后肯定也不是sql的问题,毕竟就一个最简单的count语句,接下来深入观察两张表在hdfs中的存储状态
可以发现同样的数据量,但是底层的存储文件完全不同,很明显就是小文件的问题,但是其中的差距太大了,难道小文件的破坏力这么强大?接下来统计两张表详细的分区数和小文件数量
该表有370个分区,六万多个小文件
再来看看第二张表3个分区的文件数量
到这里,问题基本上已经排查清楚了,至于怎么解决,方法是非常多的只要把文件数量减小就可以,我的解决方法是建一张sequencefile的表然后将数据导入。
测试表明,两个分区两百多个小文件原来查询耗时一分多钟,导入sequencefile的表中查询耗时只有0.1秒,进入hdfs查看了一下两个分区只有四个文件,成功解决。
在这里限于时间只是选择一个简单的方法做一下测试,证明小文件的危害性。解决小文件的办法其实是非常多的,并不算一个多复杂的问题,恶心之处在于很多时候无法避免,然后又要花额外的时间进行处理。