为什么按某些列分布会显着增加存储大小?

Why distribute by some column increase storage size dramatically?

我的程序有点奇怪,我负责处理流量日志并将处理后的数据存储在 table 中。日志太大了,我们需要想办法降低存储成本。处理后的数据,table schema有30列,其中14列是关于设备和app环境的,8列是点或页面的属性。由于我们的执行引擎是Hive,我们使用ORC作为文件格式,zlib作为压缩方式。为了让table方便BI/BA使用,我们在写入文件之前也通过point_name分发数据。 问题来了,如果我们在没有“按 xx 分配”的情况下加载数据,它需要 14.5497GB 的存储空间,当我尝试按 point_name(网络或应用程序中的点名称)分配时,存储空间将其大小加倍到28.6083GB,然后我尝试通过 cuid(设备的唯一 id)分配,存储大小为 11.7286GB,然后我尝试通过 point_name+cuid 分配,存储为 29.6391GB,我很困惑如何可以“分配”影响存储这么多。有人可以向我解释一下吗?非常感谢。

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

你的 distribute by 键与其他一些键有一些相关性,因此最终减少顶点生成的文件可能包含相似的数据或根本不相似,导致文件具有不同的熵,可以压缩更多或效率较低。

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

先尝试 sort by 一些低基数键,最后再尝试 distribute by 一些高基数键,您将看到压缩效果如何提高。排序可以将压缩的ORC文件的大小减少4倍甚至更好。