I was trying to do something similar my self with a very large table ( >100m records ) and found that using Offset / Limit was killing performance.
Offset for the first 10m records was (with limit 1) about 1.5 minutes to retrieve with it growing exponentially.
By record 50m I was up to 3 minutes per select - even using sub-queries.
I came across a post here which details useful alternatives.
I modified this slightly to suit my needs and came up with a method that gave me pretty quick results.
CREATE TEMPORARY TABLE
just_index AS SELECT ROW_NUMBER()
OVER (ORDER BY [VALUE-You-need]), [VALUE-You-need]
FROM [your-table-name];
This was a once-off - took about 4 minutes but I then had all values I wanted
Next was to create a function that would loop at the "Offset" I needed:
create or replace
function GetOffsets ()
returns void as $$
declare
-- For this part of the function I only wanted values after 90 million up to 120 million
counter bigint := 90000000;
maxRows bigInt := 120000000;
begin
drop table if exists OffsetValues;
create temp table OffsetValues
(
offset_myValue bigint
);
while counter <= maxRows loop
insert into OffsetValues(offset_myValue)
select [VALUE-You-need] from just_index where row_number > counter
limit 1;
-- here I'm looping every 500,000 records - this is my 'Offset'
counter := counter + 500000 ;
end loop ;
end ;$$ LANGUAGE plpgsql;
Then run the function:
select GetOffsets();
Again, a once-off amount of time (I went from ~3 minutes getting one of my offset values to 3 milliseconds to get one of my offset values).
Then select from the temp-table:
select * from OffsetValues;
This worked really well for me in terms of performance - I don't think i'll be using offset going forward if I can help it.
Hope this improves performance for any of your larger tables.