在PostgreSQL 9.3中,有多种方法可以构建一个表达式,它指向一个json字段的嵌套属性:
data->'foo'->>'bar'
data#>>'{foo,bar}'
json_extract_path_text(data, 'foo', 'bar')
因此,如果查询的表达式与索引的表达式完全匹配,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';
我的问题是:
这种行为是否有意?我认为当查询包含#>>
的适当调用时,查询优化器应该(至少)使用json_extract_path_text()
运算符的索引 - 反之亦然。
如果我想在我的应用程序中使用更多这些表达式(不只是一个,f.ex。坚持->
& ->>
运算符),我应该构建哪些索引? (我希望,不是所有人。)
有没有机会,一些未来的Postgres版本'优化器会理解这些表达式的等价性吗?
修改:
当我为此创建一个额外的运算符时:
CREATE OPERATOR ===> (
PROCEDURE = json_extract_path_text,
LEFTARG = json,
RIGHTARG = text[]
);
此查询(上一个示例中的表)仍未使用其索引:
EXPLAIN SELECT * FROM json_test_index3 WHERE data ===> '{foo,bar}' = 'baz';
奖金问题:
虽然Postgres将运算符扩展为函数调用(幕后),为什么还没有使用它的索引?
答案 0 :(得分:0)
您必须对JSON和JSONB数据类型使用GIN索引。 您可以将运算符参数用于计划的查询 示例:
CREATE INDEX idx_tbl_example ON tbl_example USING GIN(your_jsonb_field);
如果您计划仅使用@>运算符,则可以与jsonb_path_ops参数一起使用
CREATE INDEX idx_tbl_example ON tbl_example USING GIN(your_jsonb_field jsonb_path_ops);
其他选择是documented on postgresql site
我认为您可以使用此
CREATE INDEX idx_tbl_example ON tbl_example USING GIN(your_jsonb_field json_extract_path_text);