В 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()
-- и наоборот.
Если я хочу использовать больше этих выражений в своем приложении (не одно, например, придерживаться операторов ->
и ->>
), какие индексы мне следует построить? (надеюсь, не все).
Есть ли шанс, что некоторые оптимизаторы будущих версий Postgres поймут эквивалентность этих выражений?
ИЗМЕНИТЬ:
Когда я создаю для этого дополнительный оператор:
CREATE OPERATOR ===> (
PROCEDURE = json_extract_path_text,
LEFTARG = json,
RIGHTARG = text[]
);
Этот запрос (таблица из предыдущего примера) по-прежнему не использует свой индекс:
EXPLAIN SELECT * FROM json_test_index3 WHERE data ===> '{foo,bar}' = 'baz';
Бонусный вопрос:
В то время как Postgres расширяет операторы до вызовов функций (за кулисами), почему он до сих пор не использует свой индекс?
#>>
должен иметь возможность использовать индекс (аналогично текущим возможностям при индексировании типа данныхhstore
). Если у вас есть плоские пары ключ/значение, которые вам нужно проиндексировать, в настоящее время единственным вариантом являетсяhstore
(или дождитесь версии 9.4). - person a_horse_with_no_name   schedule 24.04.2014jsonb
полей дадут гораздо более гибкий индекс, это будет стоить производительности. Мне нужно запросить только несколько свойств внутри объекта json, а собственные индексы определенных свойств должны работать быстрее. Мне просто интересно, если есть несколько способов получить свойство, почему мне нужно создать индекс для всех из них, чтобы использовать один (в каждом случае). Или я что-то упускаю? - person pozs   schedule 24.04.2014