Postgres: как оптимизировать этот запрос, который использует несколько вызовов json_array_elements () - PullRequest
0 голосов
/ 28 августа 2018

У меня следующий запрос, который извлекает несколько столбцов данных из объекта JSON (facebook_results столбец Postgres 10 типа json).

Иногда массивы в этом объекте содержат более 10000 элементов.

Цель этого состоит в том, чтобы получить плоскую карту денормализованных данных из каждого столбца в объекте, и где есть массив, я хочу получить все столбцы с объектами, содержащимися внутри него (и, очевидно, просто дублировать данные вниз). для внешних ключей).

Ни один из самых внутренних ключей не содержит массивов, поэтому мне не нужно беспокоиться об этом. Я забочусь только о массивах matches и nodes, которые должны быть расширены.

Сейчас запрос работает, но он очень, очень медленный. Я предполагаю, потому что это из-за плохо написанного выполнения запроса, который является рекурсивным или имеет ненужные замедления сложности.

SELECT
  id AS slice_id,
  json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table' -> 'size'       AS match_size,
  json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table' -> 'score'      AS match_score,
  json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table' -> 'width'      AS match_width,
  json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table' -> 'format'     AS match_format,
  json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table' -> 'domain'     AS match_domain,
  json_array_elements(json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table' -> 'nodes') -> 'table' -> 'crawl_date' AS node_crawl_date,
  json_array_elements(json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table' -> 'nodes') -> 'table' -> 'url'        AS node_url
FROM slices
WHERE id = 169

Вот пример того, что содержится в столбце facebook_results:

{
  "table":{
    "matches": [
      {  
        "table":{  
          "nodes":[  
            {  
              "table":{  
                "crawl_date":"2013-06-21",
                "url":"http://example.com"
              }
            }
          ],
          "size":7962624,
          "score":47.059,
          "width":3456,
          "format":"MP4",
          "domain":"example.com"
        }
      }
    ]
  }
}

У кого-нибудь есть идеи, как мне это оптимизировать?

1 Ответ

0 голосов
/ 28 августа 2018

Вы можете переписать ваш запрос, используя LATERAL:

SELECT
  id AS slice_id,
  s.t -> 'size'       AS match_size,
  s.t -> 'score'      AS match_score,
  s.t -> 'width'      AS match_width,
  s.t -> 'format'     AS match_format,
  s.t -> 'domain'     AS match_domain,
  s.t2-> 'crawl_date' AS node_crawl_date,
  s.t2-> 'url'        AS node_url
FROM slices
,LATERAL (
SELECT json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table',
json_array_elements(json_array_elements(facebook_results -> 'table' -> 'matches') 
           -> 'table' -> 'nodes') -> 'table') s(t,t2)
WHERE id = 169;

Демоверсия DBFiddle

Или еще короче:

SELECT
  id AS slice_id,
  s.t   -> 'size'       AS match_size,
  s.t   -> 'score'      AS match_score,
  s.t   -> 'width'      AS match_width,
  s.t   -> 'format'     AS match_format,
  s.t   -> 'domain'     AS match_domain,
  s2.t2 -> 'crawl_date' AS node_crawl_date,
  s2.t2 -> 'url'        AS node_url
FROM slices
,LATERAL(SELECT 
  json_array_elements(facebook_results -> 'table' -> 'matches') -> 'table' ) s(t)
,LATERAL(SELECT json_array_elements(s.t -> 'nodes') -> 'table') s2(t2)
WHERE id = 169;

DBFiddle Demo2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...