在PostgreSQL 9.3中为json字段的嵌套属性创建索引的多种方法

poz*_*ozs 7 postgresql indexing json postgresql-9.3 postgresql-json

在PostgreSQL 9.3中,有多种方法可以构建一个表达式,它指向一个json字段的嵌套属性:

data->'foo'->>'bar'
data#>>'{foo,bar}'
json_extract_path_text(data, 'foo', 'bar')
Run Code Online (Sandbox Code Playgroud)

因此,如果查询的表达式与索引的表达式完全匹配,则PostgreSQL仅使用这些索引.

CREATE TABLE json_test_index1(data json);
CREATE TABLE json_test_index2(data json);
CREATE TABLE json_test_index3(data json);

CREATE INDEX ON json_test_index1((data->'foo'->>'bar'));
CREATE INDEX ON json_test_index2((data#>>'{foo,bar}'));
CREATE INDEX ON json_test_index3((json_extract_path_text(data, 'foo', 'bar')));

-- these queries use an index, while all other combinations not:

EXPLAIN SELECT * FROM json_test_index1 WHERE data->'foo'->>'bar' = 'baz';
EXPLAIN SELECT * FROM json_test_index2 WHERE data#>>'{foo,bar}' = 'baz';
EXPLAIN SELECT * FROM json_test_index3 WHERE json_extract_path_text(data, 'foo', 'bar') = 'baz';
Run Code Online (Sandbox Code Playgroud)

我的问题是:

这种行为是有意的吗?我认为查询优化器应该(至少)使用带有#>>运算符的索引,当查询包含适当的调用时json_extract_path_text()- 反之亦然.

如果我想在我的应用程序中使用更多这些表达式(不只是一个,f.ex.坚持使用->&->>运算符),我应该构建哪些索引?(我希望,不是所有人.)

有没有机会,一些未来的Pos​​tgres版本的优化器会理解这些表达式的等价性?

编辑:

当我为此创建一个额外的运算符:

CREATE OPERATOR ===> (
    PROCEDURE = json_extract_path_text,
    LEFTARG = json,
    RIGHTARG = text[]
);
Run Code Online (Sandbox Code Playgroud)

此查询(上一个示例中的表)仍未使用其索引:

EXPLAIN SELECT * FROM json_test_index3 WHERE data ===> '{foo,bar}' = 'baz';
Run Code Online (Sandbox Code Playgroud)

奖金问题:

虽然Postgres将运算符扩展为函数调用(在幕后),但为什么还没有使用它的索引呢?

小智 0

您必须对 JSON 和 JSONB 数据类型使用 GIN 索引。您可以将运算符参数用于计划的查询 示例:

CREATE INDEX idx_tbl_example ON tbl_example USING GIN(your_jsonb_field);
Run Code Online (Sandbox Code Playgroud)

如果您计划仅使用 @> 运算符,则可以与 jsonb_path_ops 参数一起使用

CREATE INDEX idx_tbl_example ON tbl_example USING GIN(your_jsonb_field jsonb_path_ops);
Run Code Online (Sandbox Code Playgroud)

其他选择记录在 postgresql 站点上

我想你可以用这个:

CREATE INDEX idx_tbl_example ON tbl_example USING GIN(your_jsonb_field json_extract_path_text);
Run Code Online (Sandbox Code Playgroud)