关于sql:使用Postgres 9.5 GIN索引和JSONB

Using Postgres 9.5 GIN indexes and JSONB

我正在尝试创建一个Postgres GIN索引来加速以下查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CREATE TABLE foo (
    id serial PRIMARY KEY,
    a jsonb NOT NULL
);

INSERT INTO foo(a) VALUES
    ('[{"b":"aaa"}, {"b":"ddd"}]'::jsonb),
    ('[{"b":"aaa"}, {"b":"aaa"}]'::jsonb),
    ('[{"b":"aaa"}]'::jsonb),
    ('[{"b":"aaa"}]'::jsonb),
    ('[{"b":"aaa"}]'::jsonb),
    ('[{"b":"bbb"}]'::jsonb),
    ('[{"b":"bbb"}]'::jsonb),
    ('[{"b":"bbb"}]'::jsonb),
    ('[{"b":"ccc"}]'::jsonb),
    ('[]'::jsonb);

SELECT DISTINCT id FROM (
    SELECT id, jsonb_array_elements(a)->>'b' AS b FROM foo
) t WHERE t.b = 'aaa'

Postgres有可能这样吗? 我也对其他选择持开放态度。 不幸的是,我无法规范表,所以我需要使用我已经拥有的表结构。


是的,您可以在此处应用GIN索引,但它可能不是特别有用:

1
2
CREATE INDEX find_fast_jsonb_value
ON foo USING GIN (a jsonb_path_ops);

现在,您仍然需要在数组中搜索匹配的键/值对。 您的查询将变为:

1
2
3
SELECT DISTINCT id
FROM foo, jsonb_array_elements(a) AS t(b)  -- Implicit LATERAL join
WHERE b @> '{"b":"aaa"}';                 -- Comparing json key/values here

这也将set-returning-function jsonb_array_elements()放在它所属的FROM子句中。