【问题标题】:Why distribute by some column increase storage size dramatically?为什么按列分配会显着增加存储大小?
【发布时间】:2021-11-24 06:52:12
【问题描述】:

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

【问题讨论】:

    标签: hive compression bigdata zlib orc


    【解决方案1】:

    distribute by 触发 reducer 步骤,每个 reducer 接收它自己的 key(s) 并生成它自己的文件,只包含这些 key,这会极大地影响压缩效率。如果数据位于单个文件中,则压缩效果比 10 个文件中的要好,如果将其排序,则要好得多,因为使用熵编码可以更好地压缩相似的数据。

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

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

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

    【讨论】:

    • 嗨@leftjoin,我只是尝试“按point_name分配”,然后是“按cuid排序”,最终存储为17.98GB,与仅按point_name(28GB)分配相比有了很大的改进.但是我还是一头雾水,distribute by后每个文件中的数据是不可变的,sort by只对每个文件中的数据进行排序,为什么会提高存储率,是不是ORC min-max属性会对文件中的每一列进行排序,与按 cuid 手动排序没有区别。
    • @ro51n 按组分配数据,使相同的键(在分布中)由相同的减速器处理(相同的键将在相同的文件中)。排序方式指示每个减速器对其数据进行排序。最小、最大索引和布隆过滤器仅在数据经过排序时才起作用,如果没有排序,每个条带可能包含相同的键,这会使索引和布隆过滤器效率低下,压缩效率也不高。 ORC 中的 min-max 索引不会触发排序,你应该明确地这样做。
    • 你需要distribute by来通过一些key在文件之间分割数据,当表被分区并且你确实通过partition key进行分发时也很有用,所以每个reducer将处理一个分区和内存消耗以及文件数量会减少。而你需要 sort 来提高索引和压缩效率
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-02
    • 2011-04-02
    • 1970-01-01
    相关资源
    最近更新 更多