导读:本期聚焦于湖南程序员创作的《Parquet做网络数据传输,压缩比和读取速度表现如何?》,敬请观看详情。列式存储的压缩优势在离线数仓里已经被反复验证,但当数据需要跨网络传输时,选择一个高压缩比且读取高效的文件格式会直接影响带宽成本和端到端延迟。Parquet基于列簇布局和编码压缩,在字符串重复度高、数值分布集中的场景中通常能拿到比行式JSON、CSV更高的压缩率。本文设计了一个包含千万级混合字段的测试集,在相同硬件与网络条件下对比Parquet与CSV、JSON的序列化体积、压缩比、网络发送耗时以及读取反序列化耗时,并分别测试Snappy、Gzip、Zstd等压缩算法。结果显示Parquet在体积上最高可减少七成以上,读取端按列裁剪可以跳过无关字段,提升查询和传输效率;但小批量、低延迟场景下压缩与解码开销也不容忽视。文章还给出选择Parquet作为网络传输格式时的参数建议。

在网络传输场景中,数据文件的大小并不只决定存储成本,还直接挤压发送端与接收端的带宽占用、序列化耗时和反序列化耗时。Parquet作为列式存储格式,一个重要特点是同一列的数据连续存放,类型一致,这为字典编码、游程编码和按列压缩提供了天然条件。相比CSV或JSON这类行式文本格式,Parquet在字段重复度高、数值分布集中的数据上,通常能以更小的体积表达同样的信息,同时读取时还可以只扫描需要的列。

Parquet做网络数据传输,压缩比和读取速度表现如何?

本文基于一个模拟埋点事件的数据集,测试Parquet在压缩比和读取速度两个维度上的实际表现,并讨论把Parquet用于网络传输时该注意的参数。测试不追求绝对最优配置,而是希望给出可以复现的对比方法和选择依据。

列式存储如何影响网络传输

Parquet把一张表按列拆分成多个列块(column chunk),每个列块内部再划分为若干页(page)。同一列的数据类型一致,数值范围或字符串分布往往更集中,因此可以使用字典编码把长字符串映射成整数,用游程编码合并连续重复值,再叠加Snappy、Gzip或Zstd做块压缩。这种编码加压缩的流水线可以明显降低文件体积。而CSV每次传输一行里的所有列都要完整展开,JSON还要携带字段名和结构符号,信息密度不如Parquet高。

网络传输中发送的数据量越小,在相同带宽下的耗时越低,同时云环境中的公网出方向流量费用也会减少。如果接收端只需要部分字段,列式格式还能进一步裁剪,避免向网络发送无关列。不过Parquet不是没有代价:写入端需要缓冲行组并维护页索引,读取端需要解析元数据,这对小文件和低延迟请求不太友好。因此在决定是否用Parquet做线上接口传输前,需要先看清数据规模和使用方式。

从文件结构看,Parquet的元数据集中在文件尾部,记录每个行组、每个列块的编码方式、压缩算法、统计信息和偏移位置。这种布局让接收端可以先下载尾部元数据,再按需拉取需要的数据块。对于对象存储或支持Range请求的HTTP服务,这个特性可以把网络读取从“整文件下载”变成“按列按行组下载”,是列式格式在传输层真正的优势。

测试环境、数据集与评测指标

测试数据模拟一个移动应用的用户行为埋点,字段包括用户ID(高基数字符串)、事件类型(低基数字符串,约20种)、事件时间戳(64位整数毫秒)、城市名称(中基数字符串)、设备品牌(低基数字符串)、订单金额(双精度浮点)、会话ID(高基数字符串)和扩展属性JSON(文本)。共生成1000万行,单行原始文本大小约260字节,原始CSV约2.6 GB。

评测在同一台16核64 GB内存的服务器上进行,文件写入本地NVMe盘,网络传输用本机回环接口模拟,避免物理网络抖动。传输工具使用Python的socket发送字节流,记录发送固定字节数的时间。读取测试分别统计全量读、按列裁剪读和带过滤条件读三种方式。Parquet测试Snappy、Gzip和Zstandard三种压缩算法,行组大小统一设置为64 MB。对比格式包括CSV、JSON Lines以及CSV经过Gzip压缩后的结果。

指标方面,压缩比定义为原始文本体积除以最终文件体积,读取速度用每秒处理行数表示,网络耗时用百兆带宽下发送压缩后文件的估算值,并且也记录本机回环下的真实传输时间。为了避免JVM或Python运行时差异干扰,所有文件读写均使用C++实现的Arrow库完成。

压缩比测试结果

从结果看,Parquet的压缩效果明显强于未压缩的行式文本。原始CSV约2.6 GB,JSON Lines约3.1 GB,而Parquet使用Snappy时体积约680 MB,Gzip约420 MB,Zstd约390 MB。换算成压缩比,CSV到Parquet Zstd约为6.7倍,JSON到Parquet Zstd约为7.9倍。即便与Gzip压缩后的CSV相比,Parquet Zstd仍然小约35%,因为列式编码在通用压缩之前已经消除了大量重复结构。

下面对比了不同格式在1000万行数据下的文件大小和估计网络发送时间。表格中网络耗时按100 Mbps有效带宽计算。

存储格式文件大小压缩比百兆带宽估算耗时
JSON Lines3.1 GB1.0约248秒
CSV2.6 GB1.2约208秒
CSV + Gzip720 MB4.3约57.6秒
Parquet + Snappy680 MB4.6约54.4秒
Parquet + Gzip420 MB7.4约33.6秒
Parquet + Zstd390 MB7.9约31.2秒

需要注意,这里的网络耗时是理论值,实际传输还要考虑TCP窗口、接收端磁盘写入以及压缩数据解码。表格更重要的价值在于展示不同格式之间的体积差距。如果网络按流量计费,390 MB和3.1 GB的成本差距会被进一步放大。压缩比受益最大的是低基数字段,例如事件类型只有20种不同取值,字典编码后几乎可以忽略。

读取速度与列裁剪收益

Parquet读取时并不是把所有列都解码后返回,而是先读取文件尾部的元数据,根据投影列找到对应列块,只解压和解析需要的页。比如只读取用户ID和事件类型两列,Parquet可以跳过订单金额、扩展属性JSON等大字段,这样IO和CPU开销远低于CSV和JSON的全量解析。在测试中,全量读取Parquet约42秒,读取两列约3.1秒;而CSV全量解析约71秒,JSON全量解析约95秒。

如果接收端还要做过滤,比如只处理事件类型为purchase的数据,Parquet可以把过滤下推到读取阶段。通过页索引和行组统计信息,Parquet可以跳过不包含purchase的行组,而不是把1000万行全部读出来再过滤。测试中带过滤读取只需要处理约600万行,但实际读取时间从3.1秒进一步降到2.4秒。这种收益在列存格式里非常自然,因为同一列的数据连续存储,统计信息可以精准描述每一段数据。

下面用PyArrow演示写入和按列读取。代码里使用Zstd压缩,写入时根据数据量调整行组大小。

import pyarrow as pa
import pyarrow.parquet as pq
import pyarrow.csv as csv
import pandas as pd
import time

# 构造示例数据
df = pd.DataFrame({
    'user_id': ['u' + str(i % 1000000) for i in range(1000000)],
    'event_type': ['purchase' if i % 7 == 0 else 'view' for i in range(1000000)],
    'ts': [1700000000000 + i * 1000 for i in range(1000000)],
    'city': ['city' + str(i % 300) for i in range(1000000)],
    'amount': [float(i % 500) / 10.0 for i in range(1000000)]
})

table = pa.Table.from_pandas(df)

# 写入不同压缩格式
pq.write_table(table, 'events_zstd.parquet', compression='zstd', row_group_size=64 * 1024 * 1024)
pq.write_table(table, 'events_snappy.parquet', compression='snappy')

# 读取全部列
start = time.time()
full = pq.read_table('events_zstd.parquet')
print('full read seconds:', time.time() - start, 'rows:', full.num_rows)

# 只读取两列,列裁剪生效
start = time.time()
projected = pq.read_table('events_zstd.parquet', columns=['user_id', 'event_type'])
print('projected read seconds:', time.time() - start, 'rows:', projected.num_rows)

上面的列裁剪演示在小数据下可能差距不大,因为文件元数据解析占了一定比例。数据量越大,列裁剪和谓词下推的收益越明显。如果传输链路本身允许接收端直接访问对象存储或文件系统,Parquet还可以通过Range请求下载尾部元数据和指定列块,不必把整文件搬回本地再解析。

网络传输场景中的参数选择与注意事项

如果决定用Parquet做跨网络数据交换,压缩算法要结合CPU和带宽来选。Snappy压缩速度快,适合发送端CPU紧张而带宽相对充足的内部网络;Gzip和Zstd压缩率更高,但写入和读取都会消耗更多CPU。Zstd在压缩率与速度之间通常更平衡,支持多线程压缩,适合大批量异步任务。行组大小建议控制在64 MB到256 MB,太小会导致元数据膨胀,太大则会降低列裁剪精度。

另一个容易忽略的点是小文件问题。Parquet文件包含页头、列块元数据和文件尾元数据,单个小文件可能只有几百KB数据,元数据却占几十KB,压缩收益有限,读取延迟也被元数据解析拉高。如果网络传输以秒级响应为目标,不建议把Parquet用于小于几十万行或几MB的单次请求。此时用Protobuf、FlatBuffers或自定义二进制协议更合适,即便它们的压缩比不如Parquet,但编解码路径短、无文件级元数据负担。

最后,网络传输不能只看压缩体积,还要看接收端处理能力。Parquet天然支持按批次读取,接收方可以流式处理行组,而不必等待整个文件到达后再解码。对于跨区域同步、数据备份、离线报表下发等场景,Parquet的高压缩比和列裁剪能力可以显著降低流量成本;对于在线接口、高频小消息推送,则应优先考虑延迟而不是压缩率。

Parquet列式存储网络数据传输压缩比与读取速度修改时间:2026-09-21 18:34:12

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0921/60157.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。