PostgreSQL:有效地将列表查询结果聚合到 JSON 对象中

PostgreSQL: Efficiently aggregate a list query result into JSON object

我需要 return 一个查询结果,在该查询中我匹配 table 中的一行,然后在 JSON 中聚合引用该行的最多 500,000 个文本值.

最初我尝试使用 jsonb_build_object 但速度很慢。这是查询的简化版本:

SELECT
    table_a.id,
    table_a.name,
    table_a.description,
    table_a.created,
    table_a.createdby,
    table_a.modified,
    table_a.modifiedby,
    jsonb_build_object( -- the aggregate takes a very long time
        SELECT
            table_b.item
        FROM
            table_b
        WHERE
            table_a.id = table_b.table_a_id
    )
FROM
    table_a
WHERE 
    table_a.id = <some_id_input>;

我的下一步是获取一个数组,然后将其转换为 JSON。这证明效率更高:

SELECT
    table_a.id,
    table_a.name,
    table_a.description,
    table_a.created,
    table_a.createdby,
    table_a.modified,
    table_a.modifiedby,
    to_jsonb( ARRAY (
        SELECT
            table_b.item
        FROM
            table_b
        WHERE
            table_a.id = table_b.table_a_id
    ))
FROM
    table_a
WHERE 
    table_a.id = <some_id_input>;

虽然效率更高,但当我需要 JSON 对象时,它会给我一个 JSON 数组...

PostgreSQL 14 中是否有一种简单有效的方法来生成我需要的内容?

加入聚合结果:

SELECT
    table_a.id,
    table_a.name,
    table_a.description,
    table_a.created,
    table_a.createdby,
    table_a.modified,
    table_a.modifiedby,
    b.items
FROM table_a
  LEFT JOIN (
    select table_a_id, jsonb_agg(table_b.item) as items
    FROM table_b
    GROUP by table_a_id
  ) b on b.table_a_id = table_a.id
WHERE 
    table_a.id = <some_id_input>;

或者在将其限制为单个 table_a.id:

时使用横向连接
SELECT
    table_a.id,
    table_a.name,
    table_a.description,
    table_a.created,
    table_a.createdby,
    table_a.modified,
    table_a.modifiedby,
    b.items
FROM table_a
  LEFT JOIN LATERAL (
    select jsonb_agg(table_b.item) as items
    FROM table_b
    WHERE table_b.table_a_id = table_a.id
  ) b on true 
WHERE 
    table_a.id = <some_id_input>;

我不确定,但如果使用本机数组 (array_agg()) 比 JSON 创建 500.000 个项目的数组更有效,我不会感到惊讶