question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Readability and performance of row_to_json vs json_build_object in generated SQL requests

See original GitHub issue

The 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;

image

json_build_object version

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

image

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:open
  • Created 3 years ago
  • Reactions:34
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

5reactions
Konardcommented, Sep 28, 2020

Ok, I found the place where row_to_json is used in code, now I have to learn Haskell…

1reaction
Antman261commented, Jan 17, 2022

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?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Create nested json from sql query postgres 9.4 - Stack Overflow
The advantage of using row_to_json over json_build_object is that all the work is done under the hood, which makes the query more readable....
Read more >
10 Best Practices to Write Readable and Maintainable SQL ...
How to write SQL queries that your team can easily read and maintain? ... queries, it might come with a readability/performances trade-off.
Read more >
Format Query Results as JSON with FOR JSON - SQL Server
When you use the FOR JSON clause, you can specify the structure of the JSON output explicitly, or let the structure of the...
Read more >
When To Avoid JSONB In A PostgreSQL Schema - Heap
There is great material for deciding which of JSON, JSONB, or hstore is right ... view raw measurements_create.sql hosted with ❤ by GitHub....
Read more >
Best practices for writing SQL queries - Metabase
Correctness, readability, then optimization: in that order. The standard warning against premature optimization applies here. Avoid tuning your SQL query ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found