为什么按列分布会显著增加存储空间?



我的程序有点奇怪,我负责处理流量日志并将处理后的数据存储在一个表中。日志如此之大,我们需要找到一个降低存储成本的好方法。处理的数据,表模式有30列,其中14列是关于设备和应用环境的,8列是点或页面的属性。由于我们的执行引擎是Hive,所以我们使用ORC作为文件格式,zlib作为压缩方式。为了使表易于BI/BA使用,我们还在写入文件之前按point_name分发数据。问题来了,如果我们加载没有"按xx分发"的数据,它需要14.5497GB的存储空间,当我尝试按point_name(网络或应用程序中的点的名称)分发时,存储空间翻了一番,达到28.6083GB,然后我尝试按cuid(设备的唯一id)分发,存储空间大小为11.7286GB,然后我尝试按point_name+cuid分发,存储空间为29.6391GB,我很困惑如何"按xx分发"。对存储影响很大。有人能给我解释一下吗?非常感谢。

distribute by触发reducer步骤,每个reducer接收它自己的密钥,并产生它自己的文件,其中只包含这些密钥,这可能会极大地影响压缩效率。如果数据位于单个文件中,则压缩效果可能比在10个文件中更好,如果对其进行排序则明显更好,因为使用熵编码可以更好地压缩类似的数据。

您的distribute by键与其他键有一定的相关性,因此最终约简顶点生成的文件可能包含相似的数据,也可能不包含相似的数据,从而导致具有不同熵的文件,这些文件可以或多或少地压缩。

ZLIB使用的算法之一是Lempel-Ziv。Lempel-Ziv算法通过将重复出现的数据替换为对未压缩数据流中先前存在的该数据的单个副本的引用来实现压缩。相同的值可以被Lempel-Ziv压缩在单个文件和单个条带中(如果数据在加载期间排序),或者相同的值可以在不同的文件或条带中,并且不能被有效压缩,因为在每个文件中它将是它自己的Lempel-Ziv压缩。这同样适用于霍夫曼编码(更频繁的值使用更短的代码编码,更少的值使用更长的代码编码)。这里重要的一点是不可能跨不同的文件进行压缩。ORC中的每个文件甚至条带都是独立压缩的。把类似的数据放在一起(分发,或者两者兼而有之)和压缩将会改善。

尝试先sort by一些低基数键,高基数键最后,除了distribute by,你会看到压缩是如何改进的。排序可以将压缩的ORC文件的大小减少x4倍甚至更好。

最新更新