趋近智
数据湖环境中的压缩不仅仅是为了节省磁盘空间。虽然降低存储成本是一个主要优势,但压缩对I/O吞吐量 (throughput)和查询延迟的影响通常更为明显。当Apache Spark或Trino等分布式查询引擎从对象存储读取数据时,操作涉及三个不同的阶段:从网络读取字节,在内存中解压这些字节,以及将数据解析成可用格式。
如果网络带宽无限,未压缩文件从磁盘传输到CPU的速度会更快,但云网络有其限制。相反,高度压缩的文件减少了网络传输时间,但解压需要大量的CPU周期。选择压缩算法的目标是平衡这些对立的因素。您旨在使总时间 最小化,定义如下:
如果CPU解压数据所需时间长于网络传输原始字节所需时间,则压缩就成了瓶颈。
在查看具体算法之前,我们必须处理压缩与分布式处理之间的相互作用。数据湖依赖于将大文件拆分成更小块(分片)的能力,这些分片可以由不同的工作节点并行处理。
某些压缩格式,例如应用于CSV文件的标准Gzip流,是不可拆分的。为了读取data.csv.gz文件中的最后一个记录,引擎必须从头开始解压整个流以定位记录边界。这迫使单个CPU核心处理整个文件,从而抵消了分布式计算的优势。
然而,当使用Apache Parquet或ORC等列式格式时,这种限制会改变。这些格式将数据分成内部的“行组”或块。压缩编解码器独立应用于每个块,而不是整个文件。因此,使用Gzip压缩的Parquet文件是完全可拆分的。查询引擎读取文件元数据,识别每个行组的字节范围,并将不同的组分配给不同的工作节点。
我们主要关注现代数据架构中普遍使用的三种编解码器:Snappy、Gzip和Zstandard (Zstd)。
Snappy为速度而设计。它不追求最大压缩比,但侧重于极高的解压速度,在现代处理器上常超过500 MB/秒。它以极小的CPU开销提供合理的尺寸缩减(通常为1.5倍到2倍)。
基于这种平衡,Snappy是Apache Parquet的默认压缩编解码器。它适合于“热”数据层,在这些层中,查询延迟是最优先事项。在用户期望几秒内得到响应的交互式分析中,Snappy的低CPU成本确保处理器将其时间用于执行查询逻辑,而不是解压字节。
基于DEFLATE的Gzip提供高压缩比(文本数据通常为3倍到4倍),但在压缩和解压过程中产生高CPU成本。在数据湖中,Gzip最适合“冷”数据或归档数据,其中存储成本是首要关注点,且访问不频繁。
当与JSON或CSV等文本格式一起使用时,Gzip会创建不可拆分的文件。应避免生成大型(多吉字节)Gzip压缩的JSON文件。相反,如果您必须将Gzip与文本一起使用,请将文件大小调整为大致等于您的目标分区大小(例如128MB - 256MB),以便内部拆分不足不会妨碍并行性。
Zstandard是Meta公司开发的一种现代算法,提供与Gzip相当的压缩比,但解压速度更接近Snappy。它具有可调节的压缩级别(范围从负值(追求速度)到22(最大压缩))。
Zstd已成为通用数据湖存储的标准建议。它相对于Gzip提供了“帕累托改进”,在标准设置下,其速度和压缩比都优于Gzip。许多组织正将其Silver和Gold表迁移到Zstd压缩的Parquet,以降低存储成本,同时不牺牲查询性能。
典型解压速度与压缩比的比较。Zstd占据有利的中间位置,兼具高压缩比和高速度。
列式文件格式的一个独特优势是能够对不同列应用不同的编码和压缩策略。由于列中的数据是统一的(例如,全部是整数或全部是时间戳),压缩算法可以运用这种同质性。
例如,包含低基数字符串数据(如country_code)的列与字典编码结合游程编码 (RLE) 效果特别好,之后再进行通用压缩。这种处理流程通常会使存储占用显著小于行式存储的同等数据。
配置数据摄取作业(使用Spark或Flink)时,通常在表或文件级别定义压缩编解码器。然而,底层写入库(如parquet-mr)会根据数据类型和统计信息自动处理编码的应用。
选择正确的算法取决于数据生命周期阶段:
以下逻辑流程概述了根据文件格式和访问模式选择编解码器的决策过程。
基于文件格式和性能要求选择压缩算法的决策树。
通过正确地将压缩算法与存储格式和查询要求对齐 (alignment),您可以避免CPU成为一个本应是I/O限制型的架构中的瓶颈。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造