Is using range on RPC recommended?

Lets say I have a very large table and I am using a database function to query it like so:
const { data, error, count } = await supabase
.schema("repairs")
.rpc("get_tickets", params, { count: "exact", head: false })
.range(100_000, 100_500);
const { data, error, count } = await supabase
.schema("repairs")
.rpc("get_tickets", params, { count: "exact", head: false })
.range(100_000, 100_500);
Would this construct the result of the whole function first before returning the ranged part from it? Because one of my background tasks keeps failing after the range gets too high with canceling statement due to statement timeout. How can I improve this? This is probably less of a supabase question but more related to postgres.
11 Replies
garyaustin
garyaustin3w ago
Also doing a count exact is very painful. Look into Postgres limit/offset which is what range is doing. https://geronimovelasco.medium.com/how-limit-and-offset-works-behind-the-scenes-in-postgresql-a09c2c063405 Make sure you follow the RLS performance tuning tips https://supabase.com/docs/guides/database/postgres/row-level-security#rls-performance-recommendations as you will be running RLS on each row and you want to minimize how much is going on in the policy.
Muezz
MuezzOP3w ago
Policy looks simple enough but it is referencing the users table and checking the role: ((( SELECT auth.uid() AS uid) = id_client) OR (( SELECT get_role() AS get_role) = 'admin'::text)). Do you mean limit offset inside the postgres function or modifiers in the js call like .limit() and .offset()? Count is painful but necessary as I need to know how much data to loop through.
garyaustin
garyaustin3w ago
RLS looks optimized. Range is using limit offset in postgres so it will go thru all rows. You also need an order but maybe that is in your function. Is there a .offset() in JS? I'm pretty sure .range() is the way to do that.
Muezz
MuezzOP3w ago
There isn't one at least on rpc() Order is in my function.
garyaustin
garyaustin3w ago
So range will be Postgres limit offset.
Muezz
MuezzOP3w ago
My question, I think, essentially boils down to this: Are the following two the same? SELECT * FROM get_tickets() LIMIT 500 OFFSET 100000; -> This is what I think Supabase does internally. SELECT * FROM get_tickets(arg_limit:=500, arg_offset:=100000);
garyaustin
garyaustin3w ago
I did something in my approach to avoid count exact. By reading in groups of say 100. I would get 101. If I get 101 then I know I have at least 1 more time to read (dropping the 101 value).
Muezz
MuezzOP3w ago
I will try that too. I am also exploring doing one query with count and the rest without it to save on this.
garyaustin
garyaustin3w ago
I think in the end you will do a limit offset in SQL no matter what. But you might try it. I'm not going to try and guess PostgREST's magic in converting things. You could see if there is info at PostgREST.org (note the T).
Muezz
MuezzOP3w ago
Okay. I will check their docs too.
garyaustin
garyaustin3w ago
Out for the night.

Did you find this page helpful?