Re: refactoring relation extension and BufferAlloc(), faster COPY - Mailing list pgsql-hackers

From Andres Freund
Subject Re: refactoring relation extension and BufferAlloc(), faster COPY
Date
Msg-id 20230221211256.ibxhwtdrvytr2hpt@awork3.anarazel.de
Whole thread Raw
In response to Re: refactoring relation extension and BufferAlloc(), faster COPY  (Jim Nasby <nasbyj@amazon.com>)
Responses Re: refactoring relation extension and BufferAlloc(), faster COPY  (Jim Nasby <nasbyj@amazon.com>)
List pgsql-hackers
Hi,

On 2023-02-21 15:00:15 -0600, Jim Nasby wrote:
> On 10/28/22 9:54 PM, Andres Freund wrote:
> > b) I found that is quite beneficial to bulk-extend the relation with
> >     smgrextend() even without concurrency. The reason for that is the primarily
> >     the aforementioned dirty buffers that our current extension method causes.
> > 
> >     One bit that stumped me for quite a while is to know how much to extend the
> >     relation by. RelationGetBufferForTuple() drives the decision whether / how
> >     much to bulk extend purely on the contention on the extension lock, which
> >     obviously does not work for non-concurrent workloads.
> > 
> >     After quite a while I figured out that we actually have good information on
> >     how much to extend by, at least for COPY /
> >     heap_multi_insert(). heap_multi_insert() can compute how much space is
> >     needed to store all tuples, and pass that on to
> >     RelationGetBufferForTuple().
> > 
> >     For that to be accurate we need to recompute that number whenever we use an
> >     already partially filled page. That's not great, but doesn't appear to be a
> >     measurable overhead.
> Some food for thought: I think it's also completely fine to extend any
> relation over a certain size by multiple blocks, regardless of concurrency.
> E.g. 10 extra blocks on an 80MB relation is 0.1%. I don't have a good feel
> for what algorithm would make sense here; maybe something along the lines of
> extend = max(relpages / 2048, 128); if extend < 8 extend = 1; (presumably
> extending by just a couple extra pages doesn't help much without
> concurrency).

I previously implemented just that. It's not easy to get right. You can easily
end up with several backends each extending the relation by quite a bit, at
the same time (or you re-introduce contention). Which can end up with a
relation being larger by a bunch if data loading stops at some point.

We might want that as well at some point, but the approach implemented in the
patchset is precise and thus always a win, and thus should be the baseline.

Greetings,

Andres Freund



pgsql-hackers by date:

Previous
From: Jim Nasby
Date:
Subject: Re: refactoring relation extension and BufferAlloc(), faster COPY
Next
From: Pavel Luzanov
Date:
Subject: Re: psql: Add role's membership options to the \du+ command