From: | Melanie Plageman <melanieplageman(at)gmail(dot)com> |
---|---|
To: | Nazir Bilal Yavuz <byavuz81(at)gmail(dot)com> |
Cc: | Andres Freund <andres(at)anarazel(dot)de>, Pg Hackers <pgsql-hackers(at)postgresql(dot)org>, Robert Haas <robertmhaas(at)gmail(dot)com>, Peter Geoghegan <pg(at)bowt(dot)ie> |
Subject: | Re: Eagerly scan all-visible pages to amortize aggressive vacuum |
Date: | 2024-12-17 22:54:31 |
Message-ID: | CAAKRu_YkgAYJrqH-5U-5A3sDMdpE4EmLf86PpdEZiLHGqDsgTA@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Thanks for the review!
On Tue, Dec 17, 2024 at 10:57 AM Nazir Bilal Yavuz <byavuz81(at)gmail(dot)com> wrote:
>
> Here are couple of code comments:
>
> === [PATCH v2 07/10] ===
>
> It took me a while to understand that heap_vac_scan_next_block() loops
> until rel_pages. What do you think about adding
> Assert(vacrel->current_block == rel_pages) before the
> pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED,
> rel_pages) and having a comment on main loop should process blocks
> until rel_pages?
I added these to the v3 I sent in [1]
> === [PATCH v2 09/10] ===
>
> + * If there are no indexes or index scanning is disabled, phase II may be
> + * skipped. If phase I identified very few dead index entries, vacuum may skip
> + * phases II and III. Index vacuuming deletes the dead index entries from the
> + * TID store.
>
> phase III is not mentioned in the previous comments. It could be
> better to first explain what phase III is before mentioning it.
>
> + * After index vacuuming is complete, vacuum scans the blocks of the relation
> + * indicated by the TIDs in the TID store and reaps the dead tuples, freeing
> + * that space for future tuples. Finally, vacuum may truncate the relation if
> + * it has emptied pages at the end.
> + *
> + * After finishing all phases of work, vacuum updates relation statistics in
> + * pg_class and the cumulative statistics subsystem.
>
> There is no clear definition of phase III here as well. I can not
> understand what phase III is and which parts the vacuum may skip.
I've attempted to address this in v3.
> === [PATCH v2 10/10] ===
>
> + /*
> + * The number of eagerly scanned blocks an eager vacuum failed to
> + * freeze (due to age) in the current eager scan region. Eager vacuums
> + * reset it to EAGER_SCAN_MAX_FAILS_PER_REGION each time they enter a
> + * new region of the relation. Aggressive vacuums also decrement this
> + * coutner but it is initialized to # blocks in the relation.
> + */
>
> s/coutner/counter
Fixed
> /* non-export function prototypes */
> +
> static void lazy_scan_heap(LVRelState *vacrel);
>
> Extra blank line.
Fixed
> + if (TransactionIdIsNormal(vacrel->cutoffs.relfrozenxid) &&
> + TransactionIdPrecedesOrEquals(vacrel->cutoffs.relfrozenxid,
> + vacrel->cutoffs.FreezeLimit))
> + oldest_unfrozen_requires_freeze = true;
> +
> + if (MultiXactIdIsValid(vacrel->cutoffs.relminmxid) &&
> + MultiXactIdPrecedesOrEquals(vacrel->cutoffs.relminmxid,
> + vacrel->cutoffs.MultiXactCutoff))
> + oldest_unfrozen_requires_freeze = true;
>
> You may want to short-circuit the second if condition with
> !oldest_unfrozen_requires_freeze but it may increase the complexity,
> up to you.
Good point. Done.
> + vacrel->eager_pages.remaining_fails = EAGER_SCAN_MAX_FAILS_PER_REGION *
> + (1 - vacrel->next_eager_scan_region_start / EAGER_SCAN_REGION_SIZE);
>
> This will always return EAGER_SCAN_MAX_FAILS_PER_REGION or 0 because
> of the integer dividing.
Ah, wow, thanks so much for catching that!
> + if (aggressive)
> + {
> + vacrel->eagerness = VAC_AGGRESSIVE;
> +
> + /*
> + * An aggressive vacuum must scan every all-visible page to safely
> + * advance the relfrozenxid and/or relminmxid. As such, there is no
> + * cap to the number of allowed successes or failures.
> + */
> + vacrel->eager_pages.remaining_fails = vacrel->rel_pages + 1;
> + vacrel->eager_pages.remaining_successes = vacrel->rel_pages + 1;
> + return;
> + }
> ...
> ...
> + if (was_eager_scanned)
> + {
> + if (vm_page_frozen)
> + {
> + Assert(vacrel->eager_pages.remaining_successes > 0);
> + vacrel->eager_pages.remaining_successes--;
> +
> + if (vacrel->eager_pages.remaining_successes == 0)
> + {
> + Assert(vacrel->eagerness == VAC_EAGER);
>
> My initial thought was that since *was_eager_scanned* is true,
> Assert(vacrel->eagerness == VAC_EAGER) should be under the top if
> condition (I assumed that was_eager_scanned is only true for eager
> vacuums, not for aggressive vacuums too) but I see your point here.
> Since you set vacrel->eager_pages.remaining_successes to
> vacrel->rel_pages + 1, vacrel->eager_pages.remaining_successes can not
> reach 0 although all pages are processed as successful. I think
> comment is needed in both places to explain why
> vacrel->eager_pages.[remaining_fails | remaining_successes] is set to
> vacrel->rel_pages + 1 and why vacrel->eagerness should be VAC_EAGER
> when was_eager_scanned is true and
> vacrel->eager_pages.remaining_successes is 0.
Makes sense. I've attempted to clarify as you suggest in v3.
- Melanie
From | Date | Subject | |
---|---|---|---|
Next Message | David Rowley | 2024-12-17 23:11:44 | Re: Pg18 Recursive Crash |
Previous Message | Melanie Plageman | 2024-12-17 22:50:31 | Re: Eagerly scan all-visible pages to amortize aggressive vacuum |