在 Postgres 中存储大量 JSON 数据是不可行的,那么有啥替代方案呢?

Posted

技术标签:

【中文标题】在 Postgres 中存储大量 JSON 数据是不可行的,那么有啥替代方案呢?【英文标题】:Storing large JSON data in Postgres is infeasible, so what are the alternatives?在 Postgres 中存储大量 JSON 数据是不可行的,那么有什么替代方案呢? 【发布时间】:2020-07-11 06:20:27 【问题描述】:

我的表的每条记录中都有大于 2kB 的大型 JSON 数据,目前,这些数据存储在 JSONB 字段中。 我的技术栈是 Django 和 Postgres。 我没有对此 json 数据执行任何更新/修改,但我确实需要频繁且快速地阅读它。但是,由于 JSON 数据大于 2kB,Postgres 将其拆分为块并放入 TOAST 表中,因此读取过程变得非常缓慢。 那么有哪些替代方案呢?我应该使用像 MongoDB 这样的另一个数据库来存储这些大型 JSON 数据字段吗? 注意:我不想从这个 JSON 中取出键并将它们变成列。此数据来自 API。

【问题讨论】:

您的替代方案将取决于上下文。也许以相关方式存储它,而不是 JSON? 如果您能提供更多细节,我可能会提供答案:您大约有多少行? JSON blob 大约有多大?您需要取回所有 JSON 还是只取回其中的一部分?您是否在查询 JSON 中的值?您对数据库服务器的硬件了解多少(是否共享/专用、多少内存、是否在 SSD 上运行等)? 我认为问题不在于 JSONB 字段,而在于数据或行大于 2kB,导致数据存储在行外。 @ResonateAlpha,您是否尝试过以其他方式压缩数据?就我个人而言,我更喜欢将东西保存在一个持久存储解决方案中,然后使用一些内存数据结构(如 Redis)来缓存数据以实现高性能读取。这样,您的平台就不会依赖于多个故障点(例如,如果 mongodb 崩溃,您的系统就会失败,而如果 Redis 失败,您的网站只会运行得更慢)。 嗨,谢谢你们的快速反应。我正在使用此表来存储来自服务器不断命中的各种 api 的响应(JSON 数据)。因此,随着 api 被击中的次数越来越多,表的大小会不断增长。现在,如果有人决定使用相同的参数访问相同的 api(例如,一周后),并且我知道响应将是相同的(我知道响应何时会通过某些 webhook 更改),我将使用这个 db读取 json 并将其发送回请求者。 我不想以相关方式存储它,因为每个 api 都有不同类型的响应,并且某些键可能并不总是出现在每个响应中。我只需要将此数据存储为 json。 【参考方案1】:

如果不了解您的具体情况,很难具体回答,但您可以尝试以下方法:

    使用 Postgres 12(已存储)generated columns 来维护通常需要的字段或较小的 JSON blob。这会增加存储开销,但您不必自己维护此副本。 Create indexes for any JSON fields 您正在查询(Postgresql 允许您为 JSON 表达式创建索引)。 使用composite index,其中索引中的第一个字段是您要查询的字段,第二个字段(/json 表达式)是您要检索的值。在这种情况下,Postgresql 应该从索引中检索值。 与1类似,创建materialised view,提取你需要的字段,让你快速查询。您也可以向物化视图添加索引。这可能是一个很好的解决方案,因为物化视图的更新速度可能很慢,但在您的情况下,您的数据无论如何都不会更新。 调查吐司表变慢的原因。我不确定您看到的性能如何,但如果您确实需要提取大量数据,那么无论您选择使用哪种数据库,您都需要快速访问数据。

您的里程可能会因上述所有建议而异,尤其是每个都取决于您的特定用例。 (请参阅我评论中的问题)

但是,总体思路是使用 Postgresql 提供的工具来快速访问您的数据。是的,这可能涉及将数据从其原始 JSON blob 中提取出来,但这不需要手动完成。 Postgresql 为此提供了一些很棒的工具。

【讨论】:

您好,感谢您的回答。我不知道物化视图是如何工作的,所以我会尝试一下。 不用担心。我从您的上述回复中意识到,虽然您没有更新行,但您正在插入行。您的物化视图需要刷新,新插入的行才会出现在其中。【参考方案2】:

如果您只需要完全存储和读取这个 json 对象而不在 WHERE 查询中使用 json 结构,那么简单地将这些数据作为二进制存储在 bytea 列中呢? https://www.postgresql.org/docs/current/datatype-binary.html

【讨论】:

以上是关于在 Postgres 中存储大量 JSON 数据是不可行的,那么有啥替代方案呢?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Rails 5 在 Postgres 中存储字符串化 JSON

使用 postgres 在 Django 中高效存储 Json

使用 postgres 构建一个触发器函数来处理 json 数据

在 Postgres 9.4 中查找 JSON 数组中的最后一项

在 Postgres 中收集递归 JSON 密钥

使用 Laravel Blade 从 Postgres 显示 JSON 数据