在 OLAP 用例中从 REST API 丰富来自 postgres table 的数据

enriching data from postgres table from a REST API in OLAP use case

我们使用 postgres 作为数据仓库,我们使用 dbt 进行管理。

里面有一个又大又细的table像这样(~1000万行):

col1 col2
'value1' 123
... ...
'valueN' 123

此外,还有一个数据扩充 API 接受现有列作为参数和 returns 相关的扩充数据:

https://api.myapi.com/&q=value1+123

每次 API 调用 returns 需要 ~1 秒

什么 is/are 性能 way/s 可以在不离开数据仓库的情况下丰富数据,这样我就可以像这样添加第三列:

col1 col2 enrichedCol
'value1' 123 enriched1
... ... ...
'valueN' 123 enrichedN

理想情况下,这是通过 SQL 或存储过程完成的。

Snowflake External Functions 实现了类似的效果。

我们考虑过 asyncio plpython3u 存储过程方法,但我觉得 postgres 应该有更好的解决方案。

为什么这样做是反模式的解释也接受table。

Postgres 和 dbt 家伙,到目前为止,看起来这在讨论中比堆栈溢出更受欢迎,但我是,很好的问题。

基本上,到目前为止我解释这个的方式,你问的是模式,公平地说,到目前为止,绝大多数 dbt 用户只使用了 1 个,也许是 2 个来自什么的架构“模式”我在这里见过。这会随着时间的推移而改变,因为我相信 Spark、Firebolt 和“下一代”数据存储可能很快就会支持“api 到数据库管道作为 sql”等功能。

我至少能想到3个选项:

  1. 转储到“数据湖”
  2. ETL/ELT 引擎
  3. 轮询服务(如您所建议)

这将是我如何粗略说明文档或项目提案的这些模式:

进一步描述这些:

  1. 将 API 中的所有内容批量转储到一个文件(或者更好的快照文件,以防某些数据稍后被编辑),然后通过 dbt-external-tables 将该数据作为视图提供以便您始终在合并视图查询时合并存档中的最新内容。

这方面的示例是在云存储服务上使用目录结构,如下文所述:Loading and transforming data into BigQuery using dbt

  1. 使用数据库中的外部服务使用数据库中的数据轮询 api。 (可能是自从 DB 读取,从 API 读取,然后写入 DB 的三重网络 IO 以来最慢的整体选项。)

** 编辑 ** (为了清楚起见,这 NOT 与源只读 ELT 服务(如 Fivetran 或 Airbyte)相同。这里我指的是使用能够在需要的情况下执行 read/update 或 read/upsert 操作,例如在数据库中查看地址 table,然后使用来自 [=65= 的地址的净化版本丰富该信息] 放置 API 或等价物)。

  1. 创建一个过程(ala this SO Postgres 问题 结合触发器,可以通过标准 cURL 调用 return 来自外部服务的值。 (我对这个问题的看法是可维护性——如果 API 发生变化并提取意外值,你将如何收到警报,你如何记录过程调用的时间和成功,你的 DE 是否可以控制数据库以及 dbt 代码库,并且可以完美地预测 dbt 更改将如何影响此过程?等)

很高兴进一步扩展,但通常建议在 [postgres][rest][webservices] 标签中重新打开这个问题,因为到目前为止,dbt 与问题几乎无关。

PG应该处理1000万! :) 我会将列添加到 table,接受空值。然后在小块中,我会逐行更新。

这里的关键因素是不要将 table 锁定太久。就重用 space.

而言,较小的事务也更好

第一步让快速独占锁真的很短。这只会更改 table 的元数据 - 因为允许空值,所以最后一列默认为空,如果行结束得更快 - 之后的所有列在设计上都是空的。

下一次更改 - 应该分块进行。这样 free-space-map 可以处理每个块,下一个应该重用前一个留下的 space。如果您需要更多信息,请阅读 MVCC。更新更改索引(也是 MVCC 解释的),添加到 FSM,如果您需要特定的数据顺序,索引结构 - 请注意。

关于反模式的问题。好吧,如果您在服务器上拥有所有数据,并且您的 PG 很新 - 您可以使用 stored procedure / anonymous block. Just commit every 1000-2000 updates. Other option - external script. I would recommend triggering it from the server with screen... Just as good practice. On the other hand - it should just pick next 1000-2000 rows with nulls, so failure should not be a big deal. If that is too much for the server - due to high load from other sources - just add some some sleep.