Re: Removing more vacuumlazy.c special cases, relfrozenxid optimizations - Mailing list pgsql-hackers
From | Peter Geoghegan |
---|---|
Subject | Re: Removing more vacuumlazy.c special cases, relfrozenxid optimizations |
Date | |
Msg-id | CAH2-WzkymFbz6D_vL+jmqSn_5q1wsFvFrE+37yLgL_Rkfd6Gzg@mail.gmail.com Whole thread Raw |
In response to | Re: Removing more vacuumlazy.c special cases, relfrozenxid optimizations (Peter Geoghegan <pg@bowt.ie>) |
Responses |
Re: Removing more vacuumlazy.c special cases, relfrozenxid optimizations
Re: Removing more vacuumlazy.c special cases, relfrozenxid optimizations |
List | pgsql-hackers |
On Fri, Dec 10, 2021 at 1:48 PM Peter Geoghegan <pg@bowt.ie> wrote: > * I'm still working on the optimization that we discussed on this > thread: the optimization that allows the final relfrozenxid (that we > set in pg_class) to be determined dynamically, based on the actual > XIDs we observed in the table (we don't just naively use FreezeLimit). Attached is v4 of the patch series, which now includes this optimization, broken out into its own patch. In addition, it includes a prototype of opportunistic freezing. My emphasis here has been on making non-aggressive VACUUMs *always* advance relfrozenxid, outside of certain obvious edge cases. And so with all the patches applied, up to and including the opportunistic freezing patch, every autovacuum of every table manages to advance relfrozenxid during benchmarking -- usually to a fairly recent value. I've focussed on making aggressive VACUUMs (especially anti-wraparound autovacuums) a rare occurrence, for truly exceptional cases (e.g., user keeps canceling autovacuums, maybe due to automated script that performs DDL). That has taken priority over other goals, for now. There is a kind of virtuous circle here, where successive non-aggressive autovacuums never fall behind on freezing, and so never fail to advance relfrozenxid (there are never any all_visible-but-not-all_frozen pages, and we can cope with not acquiring a cleanup lock quite well). When VACUUM chooses to freeze a tuple opportunistically, the frozen XIDs naturally cannot hold back the final safe relfrozenxid for the relation. Opportunistic freezing avoids setting all_visible (without setting all_frozen) in the visibility map. It's impossible for VACUUM to just set a page to all_visible now, which seems like an essential part of making a decent amount of relfrozenxid advancement take place in almost every VACUUM operation. Here is an example of what I'm calling a virtuous circle -- all pgbench_history autovacuums look like this with the patch applied: LOG: automatic vacuum of table "regression.public.pgbench_history": index scans: 0 pages: 0 removed, 35503 remain, 31930 skipped using visibility map (89.94% of total) tuples: 0 removed, 5568687 remain (547976 newly frozen), 0 are dead but not yet removable removal cutoff: oldest xmin was 5570281, which is now 1177 xact IDs behind relfrozenxid: advanced by 546618 xact IDs, new value: 5565226 index scan not needed: 0 pages from table (0.00% of total) had 0 dead item identifiers removed I/O timings: read: 0.003 ms, write: 0.000 ms avg read rate: 0.068 MB/s, avg write rate: 0.068 MB/s buffer usage: 7169 hits, 1 misses, 1 dirtied WAL usage: 7043 records, 1 full page images, 6974928 bytes system usage: CPU: user: 0.10 s, system: 0.00 s, elapsed: 0.11 s Note that relfrozenxid is almost the same as oldest xmin here. Note also that the log output shows the number of tuples newly frozen. I see the same general trends with *every* pgbench_history autovacuum. Actually, with every autovacuum. The history table tends to have ultra-recent relfrozenxid values, which isn't always what we see, but that difference may not matter. As far as I can tell, we can expect practically every table to have a relfrozenxid that would (at least traditionally) be considered very safe/recent. Barring weird application issues that make it totally impossible to advance relfrozenxid (e.g., idle cursors that hold onto a buffer pin forever), it seems as if relfrozenxid will now steadily march forward. Sure, relfrozenxid advancement might be held by the occasional inability to acquire a cleanup lock, but the effect isn't noticeable over time; what are the chances that a cleanup lock won't be available on the same page (with the same old XID) more than once or twice? The odds of that happening become astronomically tiny, long before there is any real danger (barring pathological cases). In the past, we've always talked about opportunistic freezing as a way of avoiding re-dirtying heap pages during successive VACUUM operations -- especially as a way of lowering the total volume of WAL. While I agree that that's important, I have deliberately ignored it for now, preferring to focus on the relfrozenxid stuff, and smoothing out the cost of freezing (avoiding big shocks from aggressive/anti-wraparound autovacuums). I care more about stable performance than absolute throughput, but even still I believe that the approach I've taken to opportunistic freezing is probably too aggressive. But it's dead simple, which will make it easier to understand and discuss the issue of central importance. It may be possible to optimize the WAL-logging used during freezing, getting the cost down to the point where freezing early just isn't a concern. The current prototype adds extra WAL overhead, to be sure, but even that's not wildly unreasonable (you make some of it back on FPIs, depending on the workload -- especially with tables like pgbench_history, where delaying freezing is a total loss). -- Peter Geoghegan
Attachment
pgsql-hackers by date: