Re: eliminate xl_heap_visible to reduce WAL (and eventually set VM on-access)

From: Andres Freund <andres(at)anarazel(dot)de>
To: Alexey Makhmutov <a(dot)makhmutov(at)postgrespro(dot)ru>
Cc: Melanie Plageman <melanieplageman(at)gmail(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Kirill Reshke <reshkekirill(at)gmail(dot)com>, Andrey Borodin <x4mmm(at)yandex-team(dot)ru>, Robert Haas <robertmhaas(at)gmail(dot)com>, Heikki Linnakangas <hlinnaka(at)iki(dot)fi>
Subject: Re: eliminate xl_heap_visible to reduce WAL (and eventually set VM on-access)
Date: 2026-04-06 14:44:33
Message-ID: 7clovcjtacv6peujpfaimeynrkcd4anp6ohbdd3ncgtjo67anb@ylcccepdiuz2
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

On 2026-04-06 17:30:51 +0300, Alexey Makhmutov wrote:
> Sorry for the late note for the already committed patch, but I have a
> question on the last part of the 'heap_xlog_prune_freeze' function related
> to the FSM update (it was committed in add323d -'Eliminate
> XLOG_HEAP2_VISIBLE from vacuum phase III').

FWIW, I don't think it's ever too late to look at commits, and certainly not
when it's a commit from the same release.

> Currently it contains the following logic:
>
> ...
> Size freespace = 0;
> ...
> if (BufferIsValid(buffer))
> {
> if ((xlrec.flags & (XLHP_HAS_REDIRECTIONS |
> XLHP_HAS_DEAD_ITEMS |
> XLHP_HAS_NOW_UNUSED_ITEMS)) ||
> (vmflags & VISIBILITYMAP_VALID_BITS))
> freespace = PageGetHeapFreeSpace(BufferGetPage(buffer));
> ...
> UnlockReleaseBuffer(buffer);
> }
> ...
> if (freespace > 0)
> XLogRecordPageWithFreeSpace(rlocator, blkno, freespace);
> ...
>
> My question is about the last check ('freespace > 0') - do we really want to
> call 'XLogRecordPageWithFreeSpace' only if 'freespace' is greater than 0? As
> I understand, the zero value is a perfectly valid output of the
> 'PageGetHeapFreeSpace' call (i.e. page has no space or no free line items
> while we mark all rows as frozen/visible), but with the current
> implementation we will skip FSM update in such case.

I don't have a strong opinion on this, but I think it's pretty defensible to
record only when there's free space. The whole goal of updating the FSM during
recovery is to make sure that free space can be found fairly quickly after
promotion (it's also beneficial in some crash recovery cases, but not that
much).

If the page filled up during an insert / update / delete, we will have updated
the FSM with that information at that point:

/*
* If the page is running low on free space, update the FSM as well.
* Arbitrarily, our definition of "low" is less than 20%. We can't do much
* better than that without knowing the fill-factor for the table.
*
* XXX: Don't do this if the page was restored from full page image. We
* don't bother to update the FSM in that case, it doesn't need to be
* totally accurate anyway.
*/
if (action == BLK_NEEDS_REDO && freespace < BLCKSZ / 5)
XLogRecordPageWithFreeSpace(target_locator, blkno, freespace);

The reason to update the FSM after something pruning / vacuuming related is
that there now might be *more* space available than before, it shouldn't
shrink.

Obviously the FSM is not crashsafe, so updating it with 0 during replay could
avoid some unnecessary page reads after a promotion. But I'm not sure that
that's particularly worth optimizing for.

With all that said, I'm somewhat doubtful that freespace > 0 filters out a
meaningful amount of freespace updates, it's rare for pages to be that full.

Greetings,

Andres Freund

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message John Naylor 2026-04-06 14:47:32 Re: PG 19 release notes and authors
Previous Message David G. Johnston 2026-04-06 14:42:52 Re: PG 19 release notes and authors