使用jq --stream实现JSON分组及性能优化技术问询
用jq流式处理高效合并JSON数据
需求说明
给定每行一个JSON对象的输入文件:
{"type":"a","id":"1"} {"type":"a","id":"2"} {"type":"b","id":"1"} {"type":"c","id":"3"}
需要转换成按type分组、id转为数字数组的结构:
{ "a": [1,2], "b": [1], "c": [3] }
要求用jq的--stream选项实现——因为非流式处理1G左右的大文件耗时超16小时,而用bash字符处理仅需55秒,需要一套基于JSON解析的高效jq方案。目前卡在type和id的配对上,连生成{"a":1}这类临时结构都不知道怎么弄。
高效流式处理命令
直接用这条jq命令就能搞定:
jq -n --stream ' reduce (fromstream(1|truncate_stream(inputs))) as $item ({}; .[$item.type] += [($item.id | tonumber)] ) ' input.json
命令拆解
-n:不让jq把整个输入当成单个JSON,而是用inputs逐个处理流里的内容--stream:开启流式解析,大幅降低内存占用,适合大文件fromstream(1|truncate_stream(inputs)):把流式解析出来的片段还原成完整的单个JSON对象,确保每个type和id能对应上reduce ...:从空对象开始遍历每个输入对象,把id转成数字后追加到对应type的数组里
额外优化点
- 如果输入里的
id本身就是数字类型,直接去掉| tonumber能更快 - 加
-c(也就是--compact-output)可以生成紧凑格式的JSON,进一步减少IO开销:
jq -nc --stream ' reduce (fromstream(1|truncate_stream(inputs))) as $item ({}; .[$item.type] += [$item.id] ) ' input.json
内容的提问来源于stack exchange,提问作者Martin Mucha
相关产品推荐
相关产品推荐

