JSONL 压缩:gzip vs zstd vs Brotli
JSONL 文件压缩实用指南。比较压缩比、速度基准,了解何时为数据管道、云存储和 Web 分发使用 gzip、zstd 或 Brotli。
最后更新:2026年2月
为什么要压缩 JSONL 文件?
JSONL 文件增长很快。一天的应用日志就能产生数 GB 的行分隔 JSON,机器学习数据集通常达到数十 GB。不压缩的话,您需要支付更多存储费用,传输时间更长,I/O 成为数据管道的瓶颈。在大规模场景下,压缩不是可选的 —— 它是高效处理 JSONL 数据的基础部分。
好消息是 JSONL 的压缩效果非常好。因为 JSON 是重复的文本,具有循环出现的键、分隔符和结构模式,压缩算法可以利用这种冗余实现 5 到 15 倍的大小缩减。挑战在于为您的用例选择正确的算法:gzip 提供通用兼容性,zstd 提供最佳的速度与压缩比权衡,Brotli 为静态资源实现最高压缩率。本指南通过真实基准测试、可用代码示例和清晰的建议对三者进行了比较。
压缩算法概述
三种算法主导了 JSONL 压缩领域。每种使用不同的策略,针对不同的场景进行了优化。了解它们的权衡有助于您为特定工作负载做出正确选择。
gzip (DEFLATE)
通用通用标准。gzip 自 1992 年以来一直存在,到处都支持 —— 每种编程语言、每种操作系统、每个云提供商和每个浏览器。它使用结合了 LZ77 和 Huffman 编码的 DEFLATE 算法。虽然不是最快或最高效的,但其普遍性使它成为兼容性最重要时的安全默认选择。
Zstandard (zstd)
推荐由 Facebook 于 2016 年开发,zstd 是数据压缩的现代主力。它的压缩和解压速度明显快于 gzip,同时实现相似或更好的压缩比。Zstd 还支持字典压缩,这对于每行共享相同键结构的 JSONL 文件特别有效。它是数据管道和实时处理的最佳选择。
Brotli
最高压缩比由 Google 创建,Brotli 在三者中实现最高的压缩比,特别是在最大压缩级别下。它使用 LZ77、Huffman 编码和内置的常见 Web 内容静态字典的组合。Brotli 擅长为 HTTP 传输和静态存储压缩 JSONL,但其在高级别下的压缩速度明显慢于 gzip 或 zstd。
正面对比
下表总结了压缩 JSONL 文件时最重要指标上 gzip、zstd 和 Brotli 之间的关键差异。这些是默认设置下的一般特征;实际性能因数据和压缩级别而异。
| 指标 | gzip | zstd | Brotli |
|---|---|---|---|
| 压缩比 | 良好 (5-8x) | 很好 (6-10x) | 优秀 (7-12x) |
| 压缩速度 | 中等 | 快 | 慢到中等 |
| 解压速度 | 中等 | 非常快 | 快 |
| CPU 占用 | 中等 | 低到中等 | 高(最大级别时) |
| 浏览器支持 | 所有浏览器 | Chrome 123+、Firefox 126+ | 所有现代浏览器 |
| 流式支持 | 是(原生) | 是(原生) | 有限 |
基准测试结果:100 MB JSONL 文件
为了给出具体数据,以下是压缩一个 100 MB JSONL 文件的基准测试结果。该文件包含应用日志记录,每条记录有 12 个字段,包括时间戳、日志级别、消息字符串和嵌套元数据对象。测试在配备 32 GB RAM 和 NVMe 存储的 AMD Ryzen 7 上运行。
| 算法与级别 | 压缩大小 | 压缩比 | 压缩时间 | 解压时间 |
|---|---|---|---|---|
| gzip(级别 6) | 14.2 MB | 7.0x | 2.8s | 0.9s |
| gzip(级别 9) | 13.1 MB | 7.6x | 8.4s | 0.9s |
| zstd(级别 3) | 12.8 MB | 7.8x | 0.6s | 0.3s |
| zstd(级别 1) | 15.1 MB | 6.6x | 0.3s | 0.3s |
| Brotli(级别 6) | 11.5 MB | 8.7x | 3.2s | 0.5s |
| Brotli(级别 11) | 9.8 MB | 10.2x | 42.1s | 0.4s |
基准测试代表典型的 JSONL 日志数据。结果因字段基数、值熵和记录结构而异。具有高度重复键和低熵值(如日志级别或状态码)的文件压缩效果优于具有唯一高熵字符串的文件。
压缩代码示例
以下是在 Python、Node.js 和命令行中压缩和解压 JSONL 文件的实用示例。每个示例展示了如何使用所有三种算法。
Python 内置 gzip 支持。对于 zstd 和 Brotli,安装 pyzstd 和 brotli 包。三者都遵循相同的模式:打开压缩文件句柄,然后通过它读写 JSONL 行。
import gzipimport json# === gzip (built-in) ===# Write compressed JSONLwith gzip.open('data.jsonl.gz', 'wt', encoding='utf-8') as f:for record in records:f.write(json.dumps(record, ensure_ascii=False) + '\n')# Read compressed JSONLwith gzip.open('data.jsonl.gz', 'rt', encoding='utf-8') as f:for line in f:record = json.loads(line)# === zstd (pip install pyzstd) ===import pyzstd# Write compressed JSONLwith pyzstd.open('data.jsonl.zst', 'wt', encoding='utf-8') as f:for record in records:f.write(json.dumps(record, ensure_ascii=False) + '\n')# Read compressed JSONLwith pyzstd.open('data.jsonl.zst', 'rt', encoding='utf-8') as f:for line in f:record = json.loads(line)# === Brotli (pip install brotli) ===import brotli# Compress an entire JSONL filewith open('data.jsonl', 'rb') as f:raw = f.read()compressed = brotli.compress(raw, quality=6)with open('data.jsonl.br', 'wb') as f:f.write(compressed)# Decompresswith open('data.jsonl.br', 'rb') as f:raw = brotli.decompress(f.read())for line in raw.decode('utf-8').splitlines():record = json.loads(line)
Node.js 通过 zlib 模块内置支持 gzip 和 Brotli。对于 zstd,使用 @aspect-build/zstd 或 fzstd npm 包。基于流的 API 非常适合处理大型 JSONL 文件而无需将其完全加载到内存中。
import { createReadStream, createWriteStream } from 'fs';import { createGzip, createGunzip, createBrotliCompress,createBrotliDecompress } from 'zlib';import { createInterface } from 'readline';import { pipeline } from 'stream/promises';// === gzip compress ===await pipeline(createReadStream('data.jsonl'),createGzip({ level: 6 }),createWriteStream('data.jsonl.gz'));// === gzip decompress & parse ===const gunzip = createGunzip();const rl = createInterface({input: createReadStream('data.jsonl.gz').pipe(gunzip),});for await (const line of rl) {if (line.trim()) {const record = JSON.parse(line);// process record}}// === Brotli compress ===await pipeline(createReadStream('data.jsonl'),createBrotliCompress(),createWriteStream('data.jsonl.br'));// === Brotli decompress & parse ===const br = createBrotliDecompress();const rl2 = createInterface({input: createReadStream('data.jsonl.br').pipe(br),});for await (const line of rl2) {if (line.trim()) {const record = JSON.parse(line);}}
命令行工具是压缩 JSONL 文件最快的方式。gzip 预装在所有 Unix 系统上。通过包管理器安装 zstd 和 brotli 即可使用其他两种算法。
# === gzip ===# Compress (keeps original by default with -k)gzip -k data.jsonl # -> data.jsonl.gzgzip -9 -k data.jsonl # max compression# Decompressgzip -d data.jsonl.gz# or: gunzip data.jsonl.gz# === zstd ===# Install: brew install zstd / apt install zstdzstd data.jsonl # -> data.jsonl.zstzstd -3 data.jsonl # level 3 (default)zstd --fast data.jsonl # fastest compression# Decompresszstd -d data.jsonl.zst# or: unzstd data.jsonl.zst# === Brotli ===# Install: brew install brotli / apt install brotlibrotli data.jsonl # -> data.jsonl.brbrotli -q 6 data.jsonl # quality 6brotli -q 11 data.jsonl # max compression# Decompressbrotli -d data.jsonl.br# === Piping with jq ===# Compress filtered JSONLcat data.jsonl | jq -c 'select(.level == "error")' | gzip > errors.jsonl.gz# Decompress and count lineszstd -dc data.jsonl.zst | wc -l
云存储压缩策略
在云对象存储中存储 JSONL 文件时,压缩既能减少存储成本又能缩短传输时间。大多数云提供商通过其 CDN 层支持 gzip 和 Brotli 的透明解压,但上传和存储策略有所不同。
使用正确的 Content-Encoding 头将压缩的 JSONL 上传到 S3。S3 存储压缩字节,CloudFront 可以通过自动解压来提供服务。对于数据湖工作负载,AWS Athena 和 Spark 原生读取 gzip 和 zstd 压缩的 JSONL。
guide-jsonl-compression.jsonlCompression.cloudStorage.s3.code
Google Cloud Storage 支持 gzip 透明编码。当您使用 Content-Encoding: gzip 头上传 gzip 压缩的对象时,GCS 可以在客户端发送 Accept-Encoding: gzip 时自动提供解压版本。对于 BigQuery 导入,可直接使用 gzip 压缩的 JSONL。
from google.cloud import storageimport gzipimport jsonclient = storage.Client()bucket = client.bucket('my-data-bucket')# Upload gzip-compressed JSONLdef upload_compressed(records, blob_name):blob = bucket.blob(f{blob_name}.jsonl.gz)blob.content_encoding = 'gzip'blob.content_type = 'application/x-ndjson'data = '\n'.join(json.dumps(r, ensure_ascii=False) for r in records).encode('utf-8')blob.upload_from_string(gzip.compress(data),content_type='application/x-ndjson',)# BigQuery: load compressed JSONL directly# bq load --source_format=NEWLINE_DELIMITED_JSON \# my_dataset.my_table gs://bucket/data.jsonl.gz schema.json
最佳实践:何时使用哪种算法
没有单一的最佳压缩算法。正确的选择取决于您是优先考虑存储大小、处理速度、兼容性,还是三者的平衡。以下是常见 JSONL 用例的明确建议。
归档与冷存储
使用 Brotli(质量 9-11)或 zstd(级别 19+)获得最大压缩。
归档时压缩时间不那么重要。压缩一次,很少解压。Brotli 质量 11 可以在 JSONL 数据上实现 10 倍以上的压缩,显著降低长期存储成本。
实时数据管道
使用 zstd(级别 1-3)获得最佳的速度与压缩比权衡。
在流式管道(Kafka、Kinesis、Flink)中,压缩和解压速度直接影响吞吐量和延迟。Zstd 级别 1 的压缩速度比 gzip 快,同时实现更好的压缩比。其字典模式非常适合具有固定 Schema 的 JSONL。
Web 分发与 API
静态文件使用 Brotli,gzip 作为兼容性回退。
所有现代浏览器通过 Accept-Encoding: br 支持 Brotli。Cloudflare 和 CloudFront 等 CDN 可以自动使用 Brotli 压缩。对较老客户端使用 gzip 回退。zstd 的浏览器支持正在增长但尚未普及。
ETL 与批处理
使用 gzip 获得最大兼容性,或使用 zstd 获得更好的性能。
大多数数据工具(Spark、Athena、BigQuery、pandas)原生支持 gzip。Zstd 支持正在快速改善。如果您的工具链支持 zstd,优先使用它可获得 3-5 倍更快的压缩和相当的压缩比。
试试我们的免费 JSONL 工具
上传前压缩您的 JSONL 文件,或使用我们的免费在线工具验证和转换它们。无需安装。