如何处理大型 JSONL 文件 (1GB+)
高效处理 GB 级 JSONL 数据的策略与最佳实践
最后更新:2026年2月
为什么大型 JSONL 文件需要特殊处理
当 JSONL 文件增长到数百 MB 以上时,将其完全加载到内存中就变得不切实际。一个 1GB 的 JSONL 文件如果包含复杂的嵌套对象,解析为 Python 字典或 JavaScript 对象时可能消耗 3-5GB 的内存。这可能导致应用崩溃或系统停止响应。
JSONL 相比普通 JSON 的关键优势在于它可以逐行处理。每一行都是一个独立的 JSON 文档,这意味着您永远不需要加载整个文件。这种流式处理能力使 JSONL 成为机器学习、日志分析和数据工程中处理大型数据集的首选格式。
流式读取策略
处理大型 JSONL 文件的基本方法是逐行读取,独立处理每条记录。以下是使用流行语言和工具的实现方式。
Python 的文件迭代天然就是内存高效的。for 循环每次从磁盘读取一行,无论文件大小如何都能保持恒定的内存使用量。
import jsondef process_large_jsonl(filepath: str) -> int:"""Process a large JSONL file line by line."""count = 0errors = 0with open(filepath, 'r', encoding='utf-8') as f:for line_num, line in enumerate(f, 1):line = line.strip()if not line:continuetry:record = json.loads(line)# Process your record herecount += 1except json.JSONDecodeError as e:errors += 1print(f'Line {line_num}: {e}')print(f'Processed {count} records, {errors} errors')return count
Node.js 的 readline 接口提供了使用流逐行处理文件的高效方式,即使是多 GB 的文件也能保持最小的内存使用量。
import { createReadStream } from 'fs';import { createInterface } from 'readline';async function processLargeJsonl(filepath) {const rl = createInterface({input: createReadStream(filepath, 'utf-8'),crlfDelay: Infinity,});let count = 0;for await (const line of rl) {const trimmed = line.trim();if (!trimmed) continue;try {const record = JSON.parse(trimmed);// Process your record herecount++;} catch (err) {console.error(`Parse error: ${err.message}`);}}console.log(`Processed ${count} records`);}
Unix 命令行工具非常适合快速检查和处理大型 JSONL 文件,无需编写任何代码。
# Count lines in a JSONL filewc -l data.jsonl# View first 10 recordshead -n 10 data.jsonl# View last 5 recordstail -n 5 data.jsonl# Pretty-print first recordhead -n 1 data.jsonl | jq .# Filter records with jqjq -c 'select(.age > 30)' data.jsonl# Extract specific fieldsjq -c {name, email} data.jsonl
内存管理技巧
除了基本的逐行读取之外,以下技巧可以帮助您更高效地处理大型 JSONL 文件。
以 1,000-10,000 条为一批处理记录,以平衡内存使用和处理效率。这在写入数据库或调用 API 时特别有用。
import jsonfrom typing import Iteratordef read_jsonl_batches(filepath: str,batch_size: int = 5000) -> Iterator[list]:batch = []with open(filepath, 'r') as f:for line in f:record = json.loads(line.strip())batch.append(record)if len(batch) >= batch_size:yield batchbatch = []if batch:yield batch# Usagefor batch in read_jsonl_batches('large.jsonl'):# Insert batch into databasedb.insert_many(batch)
在处理过程中监控内存使用情况,以便及早发现问题并调整批次大小。
import jsonimport psutilimport osdef process_with_monitoring(filepath: str):process = psutil.Process(os.getpid())with open(filepath, 'r') as f:for i, line in enumerate(f):record = json.loads(line)# Process recordif i % 100000 == 0:mem = process.memory_info().rss / 1024 / 1024print(f'Line {i:,}: {mem:.1f} MB')
分割大型 JSONL 文件
有时您需要将大型 JSONL 文件分割成小文件,用于并行处理、上传到有大小限制的服务,或在多台机器间分配工作。
Unix 的 split 命令是分割 JSONL 文件最快的方式。它直接按行操作,非常适合 JSONL。
# Split into files of 100,000 lines eachsplit -l 100000 data.jsonl chunk_# Split into files of approximately 100MB eachsplit -b 100m data.jsonl chunk_# Add .jsonl extension to split filesfor f in chunk_*; do mv "$f" "$f.jsonl"; done
如需更精细地控制分割逻辑,例如按字段值分割或确保输出大小均衡。
import jsondef split_jsonl(input_path: str, lines_per_file: int = 100000):file_num = 0line_count = 0out_file = Nonewith open(input_path, 'r') as f:for line in f:if line_count % lines_per_file == 0:if out_file:out_file.close()file_num += 1out_file = open(f'part_{file_num:04d}.jsonl', 'w')out_file.write(line)line_count += 1if out_file:out_file.close()print(f'Split into {file_num} files')
压缩策略
JSONL 文件的压缩效果非常好,因为 JSON 文本有很高的冗余度。压缩可以将文件大小减少 70-90%,节省存储空间并加速传输。
Python 的 gzip 模块可以透明地处理压缩的 JSONL 文件。.gz 扩展名是工具自动识别的约定。
import gzipimport json# Reading gzipped JSONLwith gzip.open('data.jsonl.gz', 'rt', encoding='utf-8') as f:for line in f:record = json.loads(line)# Process record# Writing gzipped JSONLwith gzip.open('output.jsonl.gz', 'wt', encoding='utf-8') as f:for record in records:f.write(json.dumps(record) + '\n')
压缩比较
1GB 混合数据 JSONL 文件的典型压缩率:
gzip:减少 70-80%(1GB 到 200-300MB),广泛支持
zstd:减少 75-85%(1GB 到 150-250MB),解压更快
lz4:减少 60-70%(1GB 到 300-400MB),速度最快
不压缩:访问最快,最适合频繁随机读取
在浏览器中处理大文件
jsonl.co 专为在浏览器中直接处理 1GB 以上的 JSONL 文件而设计。它使用流式处理和 Web Workers 在本地处理文件,无需上传到任何服务器。
这意味着您的数据保持私密,无需等待上传即可获得即时结果。查看器可以通过虚拟滚动显示数百万条记录,所有转换工具都支持大文件的流式处理。