如何快速将约300GB /十亿条相关记录插入PostgreSQL数据库?

问题描述

我已经为此工作了几个月,但仍然没有解决方案,希望我能从您那里得到帮助...

任务是,我需要将在线数据提供商的实时数据记录插入/导入到我们的数据库中。

实时数据以文件形式提供。每个文件包含多达200,000条json记录,一条记录一行。从2013年开始,每天都会在线提供数个/数十个文件

我计算了整个文件存储,总大小约为300GB。我估计了记录的总数(我可以通过rest api来获取文件的大小,但不能获取每个文件的行号),它应该是10亿条左右或更多。

在将一条记录导入/插入数据库之前,我需要从记录中找出两个参数(站,参数)并建立关系。

因此工作流程类似于:

  1. 数据库中查找参数,如果该参数存在于数据库中,则只需返回parameter.id;否则,应将参数作为新条目插入参数表中,并创建一个新parameter.id并返回;
  2. 类似地,在我们的数据库中查找该站点,如果该站点已经存在,则只需获取其id,否则将创建一个站点并创建一个新station.id;
  3. 然后我可以将此json记录及其标识的parameter.id和station.id插入到我们的主数据表中,以建立关系。

基本上,它是一个简单的数据库结构,具有三个主表(数据,参数,站)。它们通过parameter.id和station.id相互关联,并具有主键/外键关系。

但是查询非常耗时,而且我找不到在可预见的时间内将大量数据正确插入数据库方法

我做了两次试验:

  1. 只需对批处理插入使用普通的SQL查询。 上面描述了工作流程。 对于每个记录a)获取parameter.id b)获取station.id c)插入该记录 即使批量插入,我一周也只能插入一百万条记录。记录并不短,包含大约20个字段。

  2. 之后,我尝试了以下操作: 我没有事先检查参数和桩号,只是使用copY命令将记录复制到没有关系的中间表中。据我计算,所有十亿条记录都可以在十天内导入。 但是在copY之后,我需要使用SQL查询select distinctgroup by手动找出所有明确的工作站(只有几个参数,所以我可以忽略参数部分),并在工作站表,然后UPDATE整个记录及其相应的station.id,但是此UPDATE操作花费的时间非常长。

这里是一个示例: 我花了半天的时间将33,000,000条记录导入到中间表中。 我查询了选择longitude,latitude from records group by longitude,latitude并得到4,500个电台 我将这4,500个电台插入电台表中 而且对于我的每个电台

update record set stationid = station.id where longitude=station.longitude and latitude=station.latitude

作业仍在运行,但我估计需要两天 这仅用于3000万条记录,我有10亿条。

所以我的问题是,如何才能将如此大量的数据快速插入数据库中?

非常感谢您!


2020-08-20 10:01 非常感谢大家的评论

@Brits: 是的,不是,所有的“复制”都花费了24小时以上。一个copY”命令用于一个json文件。对于每个文件,我需要执行以下操作:

  1. 下载文件
  2. 将Json文件(不进行站间关系检查,但使用参数检查将它简单,快捷,参数就像项目中的常量一样)平铺到CSV文本文件中以进行“ copY”命令
  3. 通过Python执行“ copY”命令 如果我在公司网络中大约需要1分钟,2和3,则大约需要一分钟才能处理包含约200,000条记录的Json文件;如果我在家工作,则大约需要20分钟。 因此,只需忽略“一个半天”语句。我的估计是,如果我在公司网络中工作,我将能够在10天之内将所有300GB /十亿条记录导入中间表而无需进行关系检查。

我认为我现在的问题不是将json内容移动到平面数据库表中,而是建立数据站之间的关系。 在平板中放置json内容后,我需要找出所有站点并使用以下命令更新所有记录:

  1. 从记录组中按经度,纬度选择经度,纬度和计数(*)
  2. 将这些经度纬度组合插入到台表中
  3. 对于站表中的每个条目,执行 更新记录集stationid = station.id,其中经度= station.longitude和纬度= station.latitude

上面的这3.需要很长时间(也只有1.3亿条记录需要花费几分钟,我不知道1.十亿条记录需要花费多长时间

@Mike Organek @Laurenz Albe非常感谢。现在,即使您的评论也让我难以理解。我将研究它们并给出反馈。


文件总数为100,000+ 我正在考虑首先解析所有文件并获得单个工作站,然后预先使用station.id和parameter.id进行“复制”。我将提供反馈。


2020-09-04 09:14

我终于得到了想要的东西,即使我不确定这是否正确。

自从我提出问题以来我做了什么:

  1. 解析所有json文件并按坐标提取唯一的电台并将其保存到电台表中
  2. 使用copY命令再次解析所有json文件,并将所有字段保存到记录表中,参数ID来自常量,站ID来自1)

我在管道中进行了1)和2),它们是并行进行的。而且1)花费的时间比2)长,所以我总是需要让2)等待。

10天后,我将数据存储在postgres中,并带有ca。 15000个工作站,总计6.5亿条记录,每个记录都有对应的工作站ID。

@ steven-matison非常感谢,您能再解释一下吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)