为带有嵌套数组的 jsonb 添加和使用索引

Add and use index for jsonb with nested arrays

在我的 PostgreSQL 11.11 中,我有一个 jsonb 列包含这样的对象:

{
   "dynamicFields":[
      {
         "name":"200",
         "hidden":false,
         "subfields":[
            {
               "name":"a",
               "value":"Subfield a"
            },
            {
               "name":"b",
               "value":"Subfield b"
            }           
         ]
      }
   ]
}

dynamicFields 是一个数组,subfields 也是一个数组,我在按这样的选择时遇到性能问题:

select *
from my_table a
cross join lateral jsonb_array_elements(jsonb_column -> 'dynamicFields') df
cross join lateral jsonb_array_elements(df -> 'subfields') sf
where df ->> 'name' = '200' and sf ->> 'name' = 'a'

性能问题主要存在于 subfield。我已经添加了这样的索引:

CREATE INDEX idx_my_index ON my_table USING gin ((marc->'dynamicFields') jsonb_path_ops);

如何在 dynamicFields 中为 subfields 添加索引?
上面的查询只是一个例子,我经常用它来连接数据库中的其他表。我也知道 @> 运算符。

索引用于增强 table 上的查询性能。索引只能在 table 列上完成,并考虑将在 table 连接和 where 子句中使用的那些列使索引变得重要。对于 jsonb 列,您可以使用 gin(column_name, jsonb_path_ops).

在 table_name 上创建索引

您已经有一个很好的索引来支持您的查询。
将它与 jsonb "contains" operator" @>:

一起使用
SELECT *
FROM   my_table
WHERE  marc->'dynamicFields' @> '[{"name": "200", "subfields":[{"name": "a"}]}]';

db<>fiddle here

仔细匹配table中JSON对象的结构。然后使用索引廉价地选择行。
然后,您可以从符合条件的行中提取所需的任何部分。

详细说明:

  • Index for finding an element in a JSON array

如果其中一个过滤器本身非常有选择性,那么像您原来的那样拆分这两个条件可能会更快。无论哪种方式,两种变体都应该是 fast:

SELECT *
FROM   my_table
WHERE  marc->'dynamicFields' @> '[{"name": "200"}]'
AND    marc->'dynamicFields' @> '[{"subfields":[{"name": "a"}]}]';