Postgresql Postgres JSONB检索非常慢

Postgresql Postgres JSONB检索非常慢,postgresql,database-performance,query-performance,jsonb,Postgresql,Database Performance,Query Performance,Jsonb,在这里有点不知所措。首先也是最重要的一点,我不是dba,也没有任何博士后经验,除了我现在所做的以外 当您想要返回超过几百行的jsonb文档时,Postgres似乎会阻塞。当您试图返回数千时,查询性能会变得非常糟糕。如果您更进一步,尝试在各种表联接之后返回多个jsonb文档,那么请忘记它 下面是我的场景和一些代码: 我有3个表——所有的表都有jsonb模型,所有的模型都很复杂,其中2个是相当大的(未压缩的大小为8到12kb)。在这个特定的操作中,我需要取消一个jsonb元素数组的测试,然后再进行处

在这里有点不知所措。首先也是最重要的一点,我不是dba,也没有任何博士后经验,除了我现在所做的以外

当您想要返回超过几百行的jsonb文档时,Postgres似乎会阻塞。当您试图返回数千时,查询性能会变得非常糟糕。如果您更进一步,尝试在各种表联接之后返回多个jsonb文档,那么请忘记它

下面是我的场景和一些代码:

我有3个表——所有的表都有jsonb模型,所有的模型都很复杂,其中2个是相当大的(未压缩的大小为8到12kb)。在这个特定的操作中,我需要取消一个jsonb元素数组的测试,然后再进行处理——这给了我大约12k条记录

然后,每条记录都包含一个ID,我用它连接另一个重要的表——我需要从这个表中检索jsonb文档。从那里,我需要将该表连接到另一个(小得多)表,并根据另一个键从那里提取文档


因此,输出是几列+3个jsonb文档,范围从到您的查询很难遵循,原因如下:

  • 您的表被命名为
    tab
    table2
    table3
    ,`table4
  • 子查询为表中的每一行解析JSON,投影出一些值,然后外部查询从不使用这些值。唯一相关的是
    id
  • 外部联接必须按顺序执行,而内部联接可以自由地重新安排以提高性能。如果不知道这个查询的目的,我就不可能确定外部联接是否合适
  • 执行计划中的表名和列名与查询不匹配,所以我不相信这个计划是准确的
  • 您没有提供架构
  • 也就是说,我会尽力的

    在性能方面突出的东西 无
    where
    子句 由于没有
    where
    子句,您的查询将针对
    选项卡的每一行运行
    jsonb_array_元素
    ,这就是发生的情况。除了从JSON中提取数据并将其存储到一个单独的列中之外,我无法想象可以做多少事情来优化它

    索引不足
    无法为联接供电 查询计划表明连接可能会有相当大的成本。除了
    table1
    ,每个连接都由表的顺序扫描驱动,这意味着读取两个表的每一行。我怀疑在每个表上添加索引会有所帮助。看起来您正在加入
    id
    列,因此一个简单的
    主键
    约束将提高数据完整性和查询性能

    alter table tab add constraint primary key (id);
    alter table table2 add constraint primary key (id);
    alter table table3 add constraint primary key (id);
    alter table table4 add constraint primary key (id);
    
    类型转换 执行计划的这一部分显示了第一次联接中的双类型转换:

    Index Cond: (((elements.elem ->> 'field_id'::text))::integer = id)
    

    此谓词表示将
    选项卡
    中的
    id
    值转换为文本,然后将文本转换为整数,以便与
    表2.id
    匹配。这些转换在计算时间上可能非常昂贵,并且在某些情况下,可能会阻止索引的使用。很难给出建议,因为我不知道实际的类型是什么。

    您的查询很难遵循,原因如下:

  • 您的表被命名为
    tab
    table2
    table3
    ,`table4
  • 子查询为表中的每一行解析JSON,投影出一些值,然后外部查询从不使用这些值。唯一相关的是
    id
  • 外部联接必须按顺序执行,而内部联接可以自由地重新安排以提高性能。如果不知道这个查询的目的,我就不可能确定外部联接是否合适
  • 执行计划中的表名和列名与查询不匹配,所以我不相信这个计划是准确的
  • 您没有提供架构
  • 也就是说,我会尽力的

    在性能方面突出的东西 无
    where
    子句 由于没有
    where
    子句,您的查询将针对
    选项卡的每一行运行
    jsonb_array_元素
    ,这就是发生的情况。除了从JSON中提取数据并将其存储到一个单独的列中之外,我无法想象可以做多少事情来优化它

    索引不足
    无法为联接供电 查询计划表明连接可能会有相当大的成本。除了
    table1
    ,每个连接都由表的顺序扫描驱动,这意味着读取两个表的每一行。我怀疑在每个表上添加索引会有所帮助。看起来您正在加入
    id
    列,因此一个简单的
    主键
    约束将提高数据完整性和查询性能

    alter table tab add constraint primary key (id);
    alter table table2 add constraint primary key (id);
    alter table table3 add constraint primary key (id);
    alter table table4 add constraint primary key (id);
    
    类型转换 执行计划的这一部分显示了第一次联接中的双类型转换:

    Index Cond: (((elements.elem ->> 'field_id'::text))::integer = id)
    

    此谓词表示将
    选项卡
    中的
    id
    值转换为文本,然后将文本转换为整数,以便与
    表2.id
    匹配。这些转换在计算时间上可能非常昂贵,并且在某些情况下,可能会阻止索引的使用。很难建议该怎么做,因为我不知道实际的类型是什么。

    请显示此查询的
    解释计划。
    请使用
    解释(分析、缓冲区、格式文本)
    添加生成的问题,而不仅仅是“简单”解释第二次执行计划清楚地表明,检索12522行只需要280ms(约0.25秒)。您看到的实际查询时间的任何差异都是由网络开销和/或显示这些数据的SQL客户端造成的rows@a_horse_with_no_name公平地说,我正在使用psql,但我也尝试过pgadmin,正如您所说的那样-查询很快,因为
    alter table tab add constraint primary key (id);
    alter table table2 add constraint primary key (id);
    alter table table3 add constraint primary key (id);
    alter table table4 add constraint primary key (id);
    
    Index Cond: (((elements.elem ->> 'field_id'::text))::integer = id)