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

And*_*uiz 2 sql postgresql indexing postgresql-performance jsonb

在我的 PostgreSQL 11.11 中,我有一列jsonb保存如下对象:

{
   "dynamicFields":[
      {
         "name":"200",
         "hidden":false,
         "subfields":[
            {
               "name":"a",
               "value":"Subfield a"
            },
            {
               "name":"b",
               "value":"Subfield b"
            }           
         ]
      }
   ]
}
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

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

CREATE INDEX idx_my_index ON my_table USING gin ((marc->'dynamicFields') jsonb_path_ops);
Run Code Online (Sandbox Code Playgroud)

如何为subfields内部添加索引dynamicFields
上面的查询只是一个示例,我在与数据库中其他表的联接中经常使用它。而且我也认识@>接线员。

Erw*_*ter 6

您已经有了一个非常好的索引来支持您的查询。将其与“包含”运算符
一起使用:jsonb@>

SELECT *
FROM   my_table
WHERE  marc->'dynamicFields' @> '[{"name": "200", "subfields":[{"name": "a"}]}]';
Run Code Online (Sandbox Code Playgroud)

db<>在这里摆弄

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

详细说明:

如果其中一个过滤器本身具有很强的选择性,那么像原始过滤器那样分割两个条件可能会更快。不管怎样,两种变体都应该很快

SELECT *
FROM   my_table
WHERE  marc->'dynamicFields' @> '[{"name": "200"}]'
AND    marc->'dynamicFields' @> '[{"subfields":[{"name": "a"}]}]';
Run Code Online (Sandbox Code Playgroud)