Thread

  1. Limit memory usage by postgres_fdw batches

    Alexander Pyhalov <a.pyhalov@postgrespro.ru> — 2025-12-26T10:54:32Z

    Hi.
    
    We had some real cases when client set rather big batch_size on server 
    level, but for some foreign table, containing large documents, it was 
    inadequate and lead to OOM killer intervention. You can argue that 
    batch_size can be set on foreign table level, but it can still be not 
    flexible enough, when tuple size varies. I suppose this case is also 
    takes place for fetch_size. Issue here is that we can't somehow limit 
    size of data (versus number of rows) while fetching from cursor. But we 
    can use tuple store to preserve fetched results, so that they spill out 
    to the disk.
    
    I'm attaching two patches which try to fix issues with possible huge 
    memory usage by postgres_fdw batches.
    With fetched tuples we still can't use only tuplestore, as ctids are not 
    preserved, and so have to store them separately.
    
    The reproducer for insert is simple.
    
    create extension postgres_fdw ;
    create server loopback foreign data wrapper postgres_fdw options (dbname 
    'postgres', port '5432', batch_size '100', fetch_size '100');
    create table base_table(i int, s bytea);
    create foreign table foreign_table (i int, s bytea) server loopback 
    options(table_name 'base_table');
    create user mapping for public server loopback ;
    
    insert into foreign_table select i, 
    pg_read_binary_file('/some/big/file') from generate_series(1,1000) i;
    
    will easily grow backend RSS to several gigabytes.
    The first patch fixes this problem.
    
    The second patch alleviates the second issue - SELECT * queries also can 
    grow backend memory to several GBs. Still memory usage can peak (on my 
    toy examples) up to 3-4 GB, but at least it seams 1-2 GB less than 
    non-patched version.
    
    -- 
    Best regards,
    Alexander Pyhalov,
    Postgres Professional