Самый эффективный способ запроса данных, вложенных глубоко в массивы JSON? - PullRequest
0 голосов
/ 06 ноября 2018

В настоящее время я пишу запросы к таблице JSONB с 8 миллионами строк. Как я могу запросить объекты parent и friends наиболее эффективным способом?

Запрос (Postgres 9.6):

select distinct id, data->>'_id' jsonID, data->>'email' email, friends->>'name' friend_name, parent->>'name' parent
from temp t
CROSS JOIN jsonb_array_elements(t.data->'friends') friends
CROSS JOIN jsonb_array_elements(friends->'parent') parent
where friends ->> 'name' = 'Chan Franco'
and parent->>'name' = 'Hannah Golden'

Пример DDL (с данными): https://pastebin.com/byN7uyKx

1 Ответ

0 голосов
/ 07 ноября 2018

Ваши регулярно структурированные данные будут чище, меньше и быстрее, чем нормализованный реляционный дизайн.

Тем не менее, чтобы сделать вашу настройку намного более быстрой (если не так быстро, как нормализованный дизайн с соответствующими индексами), добавьте индекс GIN в выражение data->'friends' :

 CREATE INDEX tbl_data_friends_gin_idx ON tbl USING gin ((data->'friends'));

Затем добавьте соответствующее предложение WHERE к нашему запросу с оператором содержимого @>:


SELECT DISTINCT  -- why DISTINCT ?
       id, data->>'_id' AS json_id, data->>'email' AS email
     , friends->>'name' AS friend_name, parent->>'name' AS parent
FROM   tbl t
CROSS  JOIN jsonb_array_elements(t.data->'friends') friends
CROSS  JOIN jsonb_array_elements(friends->'parent') parent
<b>WHERE  t.data->'friends' @> '[{"name": "Chan Franco", "parent": [{"name": "Hannah Golden"}]}]'</b>
AND    friends->>'name' = 'Chan Franco'
AND    parent ->>'name' = 'Hannah Golden';

дБ <> скрипка здесь

огромная разница: с помощью индекса Postgres теперь может идентифицировать совпадающие строки до , отменяя каждый вложенный массив "друзей" в весь стол Только после того, как идентифицирует совпадающие строки в базовой таблице, вызывается jsonb_array_elements(), и результирующие строки с соответствующими элементами массива сохраняются.

Обратите внимание, что поисковое выражение должно быть допустимым JSON, соответствующим структуре массива JSON data->'friends', включая внешние скобки []. Но пропустите все пары ключ / значение, которые не должны служить фильтром.

Связанный:

Я избегал названия таблицы temp, так как это ключевое слово SQL, которое может привести к ошибочным ошибкам. Вместо этого используйте имя tbl.

...