Re: Trouble with hashagg spill I/O pattern and costing
Jeff Davis <pgsql@j-davis.com>
From: Jeff Davis <pgsql@j-davis.com>
To: Tomas Vondra <tomas.vondra@2ndquadrant.com>
Cc: pgsql-hackers@postgresql.org
Date: 2020-05-20T04:15:40Z
Lists: pgsql-hackers
Attachments
- logtape-prealloc.patch (text/x-patch) patch
On Tue, 2020-05-19 at 19:53 +0200, Tomas Vondra wrote: > > And if there a way to pre-allocate larger chunks? Presumably we could > assign the blocks to tape in larger chunks (e.g. 128kB, i.e. 16 x > 8kB) > instead of just single block. I haven't seen anything like that in > tape.c, though ... It turned out to be simple (at least a POC) so I threw together a patch. I just added a 32-element array of block numbers to each tape. When we need a new block, we retrieve a block number from that array; or if it's empty, we fill it by calling ltsGetFreeBlock() 32 times. I reproduced the problem on a smaller scale (330M groups, ~30GB of memory on a 16GB box). Work_mem=64MB. The query is a simple distinct. Unpatched master: Sort: 250s HashAgg: 310s Patched master: Sort: 245s HashAgg: 262s That's a nice improvement for such a simple patch. We can tweak the number of blocks to preallocate, or do other things like double from a small number up to a maximum. Also, a proper patch would probably release the blocks back as free when the tape was rewound. As long as the number of block numbers to preallocate is not too large, I don't think we need to change the API. It seems fine for sort to do the same thing, even though there's not any benefit. Regards, Jeff Davis
Commits
-
Use CP_SMALL_TLIST for hash aggregate
- 4cad2534da6d 13.0 landed
-
Avoid fragmentation of logical tapes when writing concurrently.
- 896ddf9b3cd7 13.0 landed