Readability and performance of row_to_json vs json_build_object in generated SQL requests
See original GitHub issueThe problem
In almost any query generated by Hasura you can find confusing (from the first sight) and no so much efficient pattern of SQL selection expression:
SELECT
row_to_json(
(
SELECT
"_1_e"
FROM
(
SELECT
"_0_root.base"."id" AS "id"
) AS "_1_e"
)
) AS "root"
--...
A solution
It turns out it is possible to get the same result in much shorter way and with about 12% performance boost as well as better readability (improves maintainability) for developers:
SELECT json_build_object('id', "_0_root.base"."id") AS "root"
--...
The source example (generated by Hasura’s analyze)
SELECT
coalesce(json_agg("root"), '[]') AS "root"
FROM
(
SELECT
row_to_json(
(
SELECT
"_1_e"
FROM
(
SELECT
"_0_root.base"."id" AS "id"
) AS "_1_e"
)
) AS "root"
FROM
(
SELECT
*
FROM
"public"."nodes"
WHERE
('true')
) AS "_0_root.base"
) AS "_2_root"
Generated from GraphQL query:
query Query {
nodes {
id
}
}
Comparison
Tested using Hasura 1.3.2 and PostgreSQL 12.3.
row_to_json version
EXPLAIN ANALYZE
SELECT
row_to_json(
(
SELECT
row
FROM
(
SELECT nodes.id
) AS row
)
) AS root
FROM nodes;

json_build_object version
EXPLAIN ANALYZE
SELECT json_build_object('id', nodes.id) AS root
FROM nodes;

Conclusion
It would be great if we can switch all queries to json_build_object version. This will impact performance (no additional Sub Plan required), bandwidth (less bytes to send from Hasura to PostgreSQL) and maintainability/readability (it will reduce time required to read, to understand and to optimize queries for developers).
In our search queries this pattern occurs more than 70 times per query, so it definitely will improve such queries.
What do you think? Should such optimization be implemented in Hasura?
Inspired by hours spent on understanding the queries and answer from StackExchange.
P.S.
The entire request can be simplified to just one line:
SELECT coalesce(json_agg(json_build_object('id', nodes.id)), '[]') AS root FROM nodes;
Issue Analytics
- State:
- Created 3 years ago
- Reactions:34
- Comments:8 (2 by maintainers)

Top Related StackOverflow Question
Ok, I found the place where
row_to_jsonis used in code, now I have to learn Haskell…I’m sorry, what is the reasoning behind deciding to convert to json in Postgres? This means my database server is doing conversions to json that my application servers could and should be doing before sending the data to the client? Why not return the data from postgres in the usual way?