如何高效快速地解析大量行格式json文件

     2023-03-12     256

关键词:

【中文标题】如何高效快速地解析大量行格式json文件【英文标题】:How to parse large amounts of line format json files efficiently and quickly 【发布时间】:2020-10-10 01:10:07 【问题描述】:

情况:

我有来自社交媒体网站的大量数据,包含 5 个月,以数分钟的行格式 json 文件分隔。 See here for explanation

所有数据都位于具有近 400 GB 内存和 32 核、64 线程 CPU 的服务器上。我一直在使用 python 的多处理模块来利用这一点,但是,我基本上必须将 29 个进程用于解析,其余的用于提取、写入和读取/删除。性能似乎并没有比我目前的配置好多少。

我创建了一个包含 5 个主要进程的程序,这些进程扩展了 python 多处理模块。每一步都有一个流程:

extracting:提取包含 1 天 1 分钟 json.bz2 文件的 tar 文件。

reading:直接从bz2文件中读取,发送json dicts到解析队列 完成 tar 文件后向删除模块发送消息。

deleting: 删除旧的 tar 文件以免占用服务器上的空间

parsing: 解析 json 字典中的关键字以进行分类、展平、放置 进入数据帧,并发送到写入队列。

write:根据类别合并写入队列中的数据帧。当主 数据帧达到一定大小,写入输出目录并丢弃。

问题:

获取数据的时间太长了。如果我按现在的方式运行程序而不停止,则需要 20 多周的时间来解析我真正想要的数据并将其分成 4 个大类,然后我将它们放入数据帧并写入 hdf5 文件。

我尝试过的:

我尝试获取 json,将其逐行放入字典中,如下所示:

with open('file') as f:
for line in f:
    json.loads(line)
    # send data to queue for parse processes

我还尝试转换为另一种数据类型以减少解析过程的一些开销:

with open('file') as f:
for line in f:
    json.loads(line)
    # categorize and convert to flattened dataframes and send
    # to parse process

我也尝试过其他方法,例如使用 pandas Series 或 Lists 代替 python dicts,但这似乎也无济于事。

当前主要解析过程的伪代码:

while True:
    while parse queue empty: wait 1 second
    item = parse_queue.get
    if parse_queue.get is None:
        break
    if item.get(keyword) is not None:
       # flatten, convert to dataframe, send to write
      # I do this for 4 different cases of items.

我也尝试过发送 pandas Series 或 Dataframes 而不是 python dicts。这似乎没有帮助。我已经尝试过在手前压平字典,这并没有改变任何东西。

访问 python dict 是 O(1)。读取过程显然足够快,可以以每秒 2-3k dicts 的速度创建 python dicts 并将其发送到解析队列(在过滤掉不需要的垃圾 json 之后)。那么为什么这个解析需要这么长时间呢?解析的时间大约是读取文件的 10-100 倍。

我认为会有所帮助的方法:

我相信我的问题只能通过直接从文件流中解析来解决,但是当这些 json 对象采用这样的文件格式时,我该如何对它们进行文件流处理呢?

我的主要问题:

如何使这个解析过程更快?我需要直接从文件流中读取吗?如果是这样,我该怎么做?

解决方案::

当您通过multiprocessing.Queue 发送大量商品时,它必须在发送时反序列化,然后消费者必须重新解析该商品。这大大减慢了您的处理时间。要么将大量的小对象组合成一个可以通过队列一次发送的大对象,要么考虑组合两个进程(例如,读取和解析 json),这样会快得多。

通过组合我创建的readparse 类解决了我之前遇到的问题后,我发现我也遇到了巨大的写入瓶颈。我通过将包含已解析 json 对象的整个文件连接到一个列表中,并通过队列将该列表发送到 write 进程来解决此问题。

关键要点:队列有很多开销并且需要大量处理时间到.get,所以找到一种方法来最小化通过队列发送的项目数量,方法是结合以下进程:不必要地抽象或将许多对象组合成一个大对象。

【问题讨论】:

检查我的answer,可能编写诸如自定义“解析器”之类的方法将是您的解决方案。 这些队列,是带线程的进程内队列还是进程间队列?提取 - 不要让它走得太远。理想情况下,提取的文件在读取时仍在文件缓存中。由于复制现有数据,逐行附加到数据帧可能会变得昂贵。最后将列表放入数据框可能会更好。 好像你json.loads(line)然后发送到另一个进程,这意味着它在下一个进程中再次被序列化和解析。 json.loads 过滤和处理可能应该在一个进程中。你有一个队列,你必须轮询和睡觉?使用有等待的队列。您是否消耗了所有 400 GB 内存?限制进程以避免颠簸。您有多个硬盘驱动器或 SSD 吗?尝试在它们之间传播 I/O - 例如,可能将 tar 提取到不同的驱动器。 是的,我一次只将一天的 tar 文件提取到服务器上的 NVME 驱动器。我相信每个 tar 文件都是一小时。所以我提取了 24 个 tar 文件,里面有 60 个文件夹,还有 60 个 .json.bz2 文件。读取过程可以非常快速地运行。我会在阅读后直接尝试解析。我不消耗所有 400 GB 的内存,我最多消耗 20-30。它似乎更占用 CPU,当我让它使用那么多内存时,我得到的回报非常递减。数据帧的实际合并只需要很少的时间(这是我在程序花费很长时间时的第一个想法) 嘿@tdelany 非常感谢。整整一周,我一直在用头撞墙。我对其进行了更改,以便在现场完成解析并且将其修复得很好。现在速度非常快。 【参考方案1】:

如果您只想更快地解析 json,您可以查看 ujson (https://pypi.org/project/ujson/)

而不是

import json
parsed = json.loads(line)

你会写

import ujson
parsed = ujson.loads(line)

但是,如果您非常了解 json 文件,您可能会尝试使用自定义正则表达式或自定义解析器来提取要提取的信息,但这些解决方案可能会在某些情况下中断,除非它们写得非常好,因为它们可能依赖 json 行来获得比 json 标准要求的更多的细节。

除此之外,我建议您分析您的代码以找出究竟是什么让您慢了下来。

可能值得这样绑定:

让一个进程读取一个文件,读取 n 行(例如 50) 将这 50 行的解析 (ujson.loads()) 委托给工作池。

多处理有相当多的开销。如果你委派了非常小的任务/元素(比如只有一行),那么多处理开销可能会大于你通过分配工作负载获得的开销)

【讨论】:

如何高效地对大量数据进行分区? [关闭]

】如何高效地对大量数据进行分区?[关闭]【英文标题】:Howtoefficientlypartitionalargeamountofdata?[closed]【发布时间】:2018-05-1811:24:48【问题描述】:我想知道在将Parquet数据存储在S3中时,什么是更有效的分区方式。在我的集群中,我... 查看详情

如何快速解析这种 JSON 格式

】如何快速解析这种JSON格式【英文标题】:HowtoparsethisJSONformatinswift【发布时间】:2020-09-2916:00:11【问题描述】:我有这种JSON格式:"version":"7.0.19","fields":["ID","pm","age","pm_0","pm_1","pm_2","pm_3","pm_4","pm_5","pm_6","conf","pm1","pm_10","p1","p2" 查看详情

iOS 高效地从 Documents Dir 中解析大型 JSON

】iOS高效地从DocumentsDir中解析大型JSON【英文标题】:iOSEfficientlyParseLargeJSONsfromDocumentsDir【发布时间】:2013-02-0121:59:03【问题描述】:当我加载我的应用程序时,我会下载大约10-15个JSON文件并将它们存储到我的应用程序文档目录... 查看详情

如何在 Oracle 18c 中高效解析 json?

】如何在Oracle18c中高效解析json?【英文标题】:HowtoparsejsonefficientlyinOracle18c?【发布时间】:2019-04-0512:31:27【问题描述】:我正在尝试使用JSON_OBJECT_T、JSON_ARRAY_TAPI解析一个大型json,它工作正常,但我想要专家建议它是否有效?... 查看详情

java高效地读取大文件

1、概述本教程将演示如何用Java高效地读取大文件。这篇文章是Baeldung(http://www.baeldung.com/)上“Java——回归基础”系列教程的一部分。2、在内存中读取读取文件行的标准方式是在内存中读取,Guava和ApacheCommonsIO都提... 查看详情

用python编写一个快速解析器

...U时间,HD不是瓶颈。我想知道在python中编写解析器有哪些高效的方法?我宁愿不要用C重写 查看详情

如何在目标c中逐行解析JSON文件

】如何在目标c中逐行解析JSON文件【英文标题】:HowtoparseaJSONfilelinebylineinobjectivec【发布时间】:2018-01-0115:33:51【问题描述】:我正在处理非常大的JSON文件,因此我不想读取整个文件然后迭代和解析每个数据条目。相反,我想迭... 查看详情

C#:尽可能高效地将大量文件放入 DVD 的代码

】C#:尽可能高效地将大量文件放入DVD的代码【英文标题】:C#:CodetofitLOTSoffilesontoaDVDasefficientlyaspossible【发布时间】:2011-04-1900:44:42【问题描述】:我需要编写一个应用程序,它将获取文件列表(一些大的,一些小的)并尽可能... 查看详情

在 Redshift 中高效地连接和聚合大量事实表

】在Redshift中高效地连接和聚合大量事实表【英文标题】:JoiningandAggregatingaLargeNumberofFactTablesEfficientlyinRedshift【发布时间】:2021-07-2115:03:23【问题描述】:我在Redshift中有许多(10M+行)事实表,每个都有一个自然键memberid,每个... 查看详情

如何在 C# 中高效地编写大型文本文件?

】如何在C#中高效地编写大型文本文件?【英文标题】:HowtoefficientlywritealargetextfileinC#?【发布时间】:2011-03-2508:20:09【问题描述】:我正在C#中创建一个方法,它为GoogleProductFeed生成一个文本文件。提要将包含超过30,000条记录,... 查看详情

如何高效地向redis写入大量的数据

...dis管道功能支持的是RedisProtocol,而不是直接的Redis命令。如何转化,可参考后面的脚本。3.利用管道插入catdata.txt|redis-cli--pipeShellVSRedispipe下面通过测试来具体看看Shell批量导入和Redispipe之间的效率。测试思路:分别通过shell脚本... 查看详情

如何高效地向redis写入大量的数据

...dis管道功能支持的是RedisProtocol,而不是直接的Redis命令。如何转化,可参考后面的脚本。3.利用管道插入catdata.txt|redis-cli--pipeShellVSRedispipe下面通过测试来具体看看Shell批量导入和Redispipe之间的效率。测试思路:分别通过shell脚本... 查看详情

如何轻松地将多维 JSON 解析为 html?

】如何轻松地将多维JSON解析为html?【英文标题】:HowtoparsemultidimensionalJSONtohtmleasily?【发布时间】:2014-11-1918:42:39【问题描述】:我想轻松地将json解析为html。我有一个多维json。所以我想轻松地将其解析为html。有任何插件或任... 查看详情

如何高效地使用sublimetext

参考技术A熟练使用Sublime快捷键之MacMac备注:具体符号对应的按键⌘Commandkey⌃Controlkey⌥Optionkey⇧ShiftKey为了方便大家记忆,将快捷键分成了8个类型,分别为Edit(编辑)Selection(光标选中)Find(查找)View(视图)Goto(跳转)Projec... 查看详情

高效地将数百万个 JSON 文件附加到单个文件中

】高效地将数百万个JSON文件附加到单个文件中【英文标题】:AppendmillionsofJSONfilesintoasinglefileefficiently【发布时间】:2016-10-1315:21:55【问题描述】:我有数百万个json文件,我需要将它们作为jsondicts列表附加到单个json文件中:每个... 查看详情

我如何解析来自 openlibrary api 的 Json 数据? (适当地)

】我如何解析来自openlibraryapi的Json数据?(适当地)【英文标题】:HowdoiparseJsondatafromopenlibraryapi?(properly)【发布时间】:2015-09-2920:33:58【问题描述】:如果这个问题已经得到解答,请原谅我。我已经看到了关于json数据和openlibrary... 查看详情

快速高效地获取屏幕(视图)黑色像素

...我正在搜索已经提出的问题,但所有这些问题都只是描述如何获取UIImage的像素颜色(我已经这样做了,但在我的情况下不是最好的解决方案)。我想检查我屏幕的所有像素并获取黑色像素或几乎黑色(非常暗)像素的数量。我... 查看详情

如何高效地构建 QT 应用程序?

】如何高效地构建QT应用程序?【英文标题】:HowtobuildaQTApplicationefficently?【发布时间】:2017-11-2311:11:03【问题描述】:我目前正在构建一个桌面软件。由于我的图形技能有限,我选择了C++QT以使其快速和干净(在.ui文件之上,我... 查看详情