代码之家  ›  专栏  ›  技术社区  ›  Tallboy

postgres:如何优化使用多个json_array_elements()调用的查询

  •  1
  • Tallboy  · 技术社区  · 6 年前

    我有以下查询,它从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_结果 专栏:

    {
      "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 回复  |  直到 6 年前
        1
  •  3
  •   Lukasz Szozda    6 年前

    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 Demo

    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