У меня есть таблица с ~ 1,4 миллионами строк. Есть около 5 столбцов с общей информацией о каждой строке и 6-й столбец с ~ 1700 парами значений ключа JSON.
Я строю некоторые сводки из столбца, называемого собственностью, выбирая строки, в которых существует определенное значение ключа. Приведенный ниже запрос выполняется за 14,5 с.
SELECT ownership,
SUM (TO_NUMBER(jsonfield->>'firstvalue','9G999g999')) AS total
FROM
mytable
WHERE
jsonfield->>'firstvalue' IS NOT NULL
group by ownership
Мои запросы будут намного больше, и я знаю, что мне нужно будет сделать выбор по многим ключевым значениям из jsonfield. Например, если добавить еще одно значение ключа, время запроса увеличится до 22,9 с.
SELECT ownership,
SUM (TO_NUMBER(jsonfield->>'firstvalue','9G999g999')) AS total,
SUM (TO_NUMBER(jsonfield->>'secondvalue','9G999g999')) AS totaltwo
FROM
mytable
WHERE
jsonfield->>'firstvalue' IS NOT NULL
OR
jsonfield->>'secondvalue' IS NOT NULL
group by ownership
Могут быть случаи, когда мне нужно будет запросить несколько сотен потенциальных значений в поле json. Любые предложения о том, как оптимизировать мои запросы, которые могут ускорить работу?
Отличный ответ ниже. К вашему сведению, мне пришлось преобразовать свой json в jsonb, прежде чем я смог создать индекс. Сначала я создал копию столбца json с именем jsonbsummary, которую затем преобразовал в jsonb.
ALTER TABLE mytable
ALTER COLUMN jsonbsummary
SET DATA TYPE jsonb
USING jsonbsummary::jsonb;
В качестве дополнительной информации: те запросы с группировкой, которые изначально занимали более 22 секунд, теперь выполняются за 200 мс с индексом GIN! Смотри ниже
SELECT ownership,
SUM (TO_NUMBER(jsonbsummary->>'firstvalue','9G999g999')) AS total,
SUM (TO_NUMBER(jsonbsummary->>'secondvalue','9G999g999')) AS totaltwo
FROM
mytable
WHERE
jsonbsummary ?| array['firstvalue','secondvalue']
group by ownership

Вам нужен Индекс ГИН в столбце JSONB.
CREATE INDEX idx_json ON mytable USING GIN (jsoncolumn);
Чтобы проверить наличие ключей, вам нужно использовать ?|оператор, который может использовать этот индекс:
select ...
from mytable
where jsoncolumn ?| array['firstvalue', 'secondvalue'];
Это эквивалентно вашему состоянию OR. Если вы хотите найти строки, содержащие все эти ключи, используйте вместо этого ?&.
Это здорово! Мне пришлось преобразовать мой json в jsonb, прежде чем это запустится. Я добавил эту деталь в свой вопрос