【问题标题】:Selecting from JSONB field slow从 JSONB 字段中选择慢
【发布时间】:2019-02-12 07:35:35
【问题描述】:

我有一个相对较小的表(约 50k 行)。当我选择所有记录时,大约需要 40 秒。该表有 3 个 JSONB 列。当我选择除 JSONB 之外的每一列时,查询大约需要 700 毫秒。

如果我只添加一个 JSONB 字段,查询时间会跳到近 10 秒。

我从不使用 where 子句来引用 JSONB 中的内容,只是选择 *.尽管如此,我还是尝试添加 GIN 索引,因为我看到它们经常被提及为 JSONB 的性能提升器。

我已经完全抽空了。

Postgres 9.6 版

 explain (analyze, buffers) select * from message;
   Seq Scan on message  (cost=0.00..5541.69 rows=52969 width=834) (actual 
   time=1.736..116.183 rows=52969 loops=1)
     Buffers: shared hit=64 read=4948
   Planning time: 0.151 ms
   Execution time: 133.555 ms

【问题讨论】:

    标签: postgresql jsonb


    【解决方案1】:

    Jsonb 是 PostgreSQL varlena 数据类型 - 这意味着当值长于 2KB 时,它将存储在辅助表(名为 TOAST 表)中。指向 TOAST 表的指针存储在主表中。所以当你不碰Jsonb列时,那么这个值就不会被读取。

    GIN 索引在这种情况下没有帮助。它仅有助于搜索。

    50K 值上的 10 秒时间很长 - 也许您的 Jsonb 值很长,或者您的 IO 系统性能不佳。请检查表的大小,并检查 IO 的性能。便宜的云机器通常IO很糟糕。

    速度变慢的另一个可能原因是 Jsonb 数据类型的复杂性。 Jsonb 是 json 子对象的序列化树。如果您不需要 Jsonb 数据类型的一些特殊功能,则使用 JSON 数据类型。这只是测试(仅在输入时检查 JSON 格式)。 JSONB的输出比Jsonb快,因为JSON内部是文本,不需要任何操作。 Jsonb的输出应该是序列化的,哪个更贵。

    【讨论】:

    • 感谢您的信息。有些大于 2kb,有些则不是。在我的 macbook pro 上它甚至很慢,尽管速度更快
    • @ZekeAlexandreNierenberg - 如果你只是存储 JSON 值而不在里面搜索,那么你可以使用 JSON 类型而不是 Jsonb。 Jsonb 格式更复杂,反序列化难度更大。
    • 转换为 JSON 帮助很大。仍然不如没有列的性能那么可靠,但它工作得非常好。继续把它添加到答案中,我会标记它是正确的!
    • @ZekeAlexandreNierenberg - 我在那里写了笔记。每次访问 TOAST 数据都会变慢。它是可测量的类型文本。这是想要的功能。几乎所有时候,您都需要快速访问一些数字、短字段 - 成本、计数、名称、.. 长字段(如注释、cmets)通常并不重要。当然,也有例外。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-01
    • 1970-01-01
    • 2020-05-03
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多