如何从100GB+流式JSON日志文件中提取唯一值?
处理大体积JSON日志提取唯一字段值的方案
先修正输入格式(关键前提)
你提供的输入JSON格式不符合规范,外层{}包裹多个JSON对象是无效写法,需要调整为以下两种合法格式之一:
- JSON数组格式:外层用
[]包裹所有对象,对象间用逗号分隔 - NDJSON(每行一个JSON对象):每个JSON对象单独占一行,无需外层包裹
方案1:jq流式处理 + awk内存去重(内存友好)
如果目标字段的唯一值数量在内存可承载范围内(比如百万级以内),用这个组合高效处理:
针对JSON数组格式:
用jq的流式解析模式避免加载整个文件,提取字段后用awk关联数组去重:
curl <远程文件URL> | jq --stream -n 'fromstream(1|truncate_stream(inputs)) | .caller' | awk '!seen[$0]++'
--stream:让jq逐块解析JSON,不加载全量数据到内存fromstream(1|truncate_stream(inputs)):解析数组格式的流式输出,提取每个独立JSON对象awk '!seen[$0]++':用关联数组记录已出现的字段值,仅输出首次出现的内容,实现内存级去重
针对NDJSON格式:
直接提取字段后用awk去重,写法更简洁:
curl <远程文件URL> | jq -r '.caller' | awk '!seen[$0]++'
-r:让jq输出原始字符串,而非带引号的JSON格式字符串
方案2:超大唯一值场景(磁盘辅助去重)
如果目标字段的唯一值数量多到内存无法承载,用磁盘临时文件辅助排序去重:
# JSON数组格式 curl <远程文件URL> | jq --stream -n 'fromstream(1|truncate_stream(inputs)) | .caller' | sort -u # NDJSON格式 curl <远程文件URL> | jq -r '.caller' | sort -u
sort -u:先排序再去重,自动使用磁盘临时文件处理大体积数据,无需加载全量内容到内存,但处理速度比内存去重慢
额外优化技巧
- 若远程主机可执行命令,先在远程端完成字段提取,减少传输数据量:
ssh <远程主机> "cat /path/to/log.json | jq --stream -n 'fromstream(1|truncate_stream(inputs)) | .caller'" | awk '!seen[$0]++' - 用
pv命令监控传输和处理进度:curl <远程文件URL> | pv | jq -r '.caller' | awk '!seen[$0]++'
内容的提问来源于stack exchange,提问作者ssq
相关产品推荐
相关产品推荐

