优化对 jsonb 数组上索引的 postgresql 查询

问题描述 投票:0回答:1

我有桌子:

  1. 请求(id:int,current_stage_id:int,selection_id:int)
  2. 选择(id:int,设置:jsonb)

Settings 有类似 {id: int, stage_type: int} 的数组。 例如:[{id: 1, stage_type: 2}, {id: 2, stage_type: 5}]

如果 current_stage_id 属于某种阶段类型,我需要查询请求。有很多选择和很多请求 - 所以我需要使用索引或其他。

我创建了索引 - 但它没有被使用。 使用 gin 创建索引 ix_selection_stage_setting ON 选择(设置 jsonb_path_ops);

当前请求如下所示:

with stage_settings as (SELECT stage.id as stage_id, stage.stage_type, rs.id as selection_id
FROM selection rs,
jsonb_to_recordset(rs.settings) AS stage(id INT, stage_type INT))
SELECT r.id, r.selection_id, r.current_stage_id 
FROM request r
JOIN stage_settings ss on ss.stage_id = r.current_stage_id AND ss.selection_id = r.selection_id
WHERE ss.stage_type = 1;

我需要更改它以使用索引或其他优化。物化视图被一位高级员工拒绝了。

postgresql optimization indexing jsonb explain
1个回答
0
投票

数据模型很糟糕。如果您存储键值对数组而不是以关系方式对其进行建模,这就是您所得到的结果。

您的查询不可能表现良好。

如果按如下方式重写查询,如果

request
不是太大,它有可能会更快:

SELECT r.id, r.selection_id, r.current_stage_id
FROM request AS r
WHERE EXISTS (SELECT FROM selection AS rs
              WHERE r.selection_id = rs.id
                AND rs.settings @> jsonb_build_object(
                                      'id', r.current_stage_id,
                                      'stage_type', 1
                                   )
             );

除了 GIN 索引之外,您还应该在

selection.id
上拥有一个索引(如果它还不是您的主键)。

如果

selection
很小,以下版本可能会更好:

SELECT DISTINCT
       r.id, r.selection_id, r.current_stage_id
FROM request AS r
   JOIN selection AS rs
      ON r.selection_id = rs.id
         AND rs.settings @> jsonb_build_object(
                               'id', r.current_stage_id,
                               'stage_type', 1
                            );
© www.soinside.com 2019 - 2024. All rights reserved.