Postgresql Postgres JSONB检索非常慢
在这里有点不知所措。首先也是最重要的一点,我不是dba,也没有任何博士后经验,除了我现在所做的以外 当您想要返回超过几百行的jsonb文档时,Postgres似乎会阻塞。当您试图返回数千时,查询性能会变得非常糟糕。如果您更进一步,尝试在各种表联接之后返回多个jsonb文档,那么请忘记它 下面是我的场景和一些代码: 我有3个表——所有的表都有jsonb模型,所有的模型都很复杂,其中2个是相当大的(未压缩的大小为8到12kb)。在这个特定的操作中,我需要取消一个jsonb元素数组的测试,然后再进行处理——这给了我大约12k条记录 然后,每条记录都包含一个ID,我用它连接另一个重要的表——我需要从这个表中检索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元素数组的测试,然后再进行处
因此,输出是几列+3个jsonb文档,范围从到您的查询很难遵循,原因如下:
tab
,table2
,table3
,`table4id
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)