Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: Pass arguments to RPCs called via GET directly #3643

Merged

Conversation

wolfgangwalther
Copy link
Member

@wolfgangwalther wolfgangwalther commented Jul 8, 2024

Previously they were passed as a JSON payload. This results in a LATERAL join for the calling expression, which prevents LIMIT from being pushed into the inlined function call, making some requests really slow.

Resolves #2858

I'm actually quite surprised that all tests were still passing when I made the build pass. I have not tried to confirm that this makes the respective RPC calls faster, but I'm pretty certain it should do so. I observed the same thing as @steve-chavez did in #2858 (comment) in one of my projects.

@wolfgangwalther wolfgangwalther force-pushed the direct-function-calls branch 3 times, most recently from b9b4496 to 84cf759 Compare July 8, 2024 17:11
@wolfgangwalther
Copy link
Member Author

Taking the examples from #2858:

The old query looked like this:

SELECT "pgrst_call".*
FROM ( SELECT '{"unseen_only":"true","uid":"AJwLWoo3xue32XIiAVrL5SyR1WB2","max_num":"300"}'::jsonb AS json_data) pgrst_payload,
LATERAL (SELECT CASE WHEN jsonb_typeof(pgrst_payload.json_data) = 'array' THEN pgrst_payload.json_data ELSE jsonb_build_array(pgrst_payload.json_data) END AS val) pgrst_uniform_json,
LATERAL (SELECT "uid", "unseen_only", "max_num" FROM jsonb_to_recordset(pgrst_uniform_json.val) AS _("uid" text, "unseen_only" boolean, "max_num" integer) LIMIT 1) pgrst_body,
LATERAL "test"."get_notifications"("uid" := pgrst_body."uid", "unseen_only" := pgrst_body."unseen_only", "max_num" := pgrst_body."max_num") pgrst_call;

The new query looks like this:

SELECT "pgrst_call".*
FROM "test"."get_notifications"("uid" := 'AJwLWoo3xue32XIiAVrL5SyR1WB2', "unseen_only" := true, "max_num" := 300) pgrst_call;

@steve-chavez
Copy link
Member

The new query looks like this

Looks good! I think the plan cost should improve with that new query. If so, perhaps we can test it on PlanSpec.hs?

@wolfgangwalther
Copy link
Member Author

I think the plan cost should improve with that new query. If so, perhaps we can test it on PlanSpec.hs?

I guess it should, yes. I will have a look.

@wolfgangwalther
Copy link
Member Author

I think the plan cost should improve with that new query. If so, perhaps we can test it on PlanSpec.hs?

I guess it should, yes. I will have a look.

I lowered the existing cost expectations for function calls with arguments as they were done with GET.

Previously they were passed as a JSON payload. This results in a LATERAL
join for the calling expression, which prevents LIMIT from being pushed
into the inlined function call, making some requests really slow.

Resolves PostgREST#2858
@wolfgangwalther wolfgangwalther merged commit ee4bfbf into PostgREST:main Jul 9, 2024
21 of 22 checks passed
@wolfgangwalther wolfgangwalther deleted the direct-function-calls branch July 9, 2024 06:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Postgrest calling function gives very different query plan from console
2 participants