Future work, deliberately not scheduled. Filing it so the gap is recorded where it
is visible rather than discovered by a user, per #395.
The gap
pgColumnar has maintenance operations that PostgreSQL's own autovacuum daemon will
never invoke, because they are extension functions rather than table-AM callbacks:
| operation |
reached by autovacuum? |
pgcolumnar_relation_vacuum (visibility map, retire fully-deleted groups) |
yes, it is the AM callback |
pgcolumnar.vacuum() (the space-reclaiming rewrite) |
no |
pgcolumnar.vacuum_sorted() / clustering decay |
no |
a future pgcolumnar.analyze() (#414) |
no |
So the cheap online part is automatic and the expensive part is manual. A user who
never runs the functions accumulates reclaimable space and, if #414 goes ahead,
increasingly stale statistics.
The asymmetry matters: a table that is never rewritten wastes disk, which is visible
and survivable. Statistics that are never refreshed produce bad plans, which is
invisible and is felt as "the database got slower" with no obvious cause. That is the
argument for solving scheduling before adding more manual maintenance functions, and
it is why #414 is gated on this.
What it would be
A background worker registered from _PG_init, in the shape of core's autovacuum
launcher: a launcher that wakes on an interval and starts per-database workers, each
deciding what needs attention and doing it.
The decisions that need answering first, none of which are code
- What triggers work. Autovacuum uses row-change counters from the statistics
collector. Our triggers are different in kind: reclaimable fraction (dead rows over
live), clustering decay (pgcolumnar.sort_status, which already measures it), and
staleness for analyze. Each needs a threshold and a GUC, and thresholds invented
without measurement are how a daemon becomes a support burden.
- Not fighting autovacuum. The AM callback already runs under autovacuum and does
the online work. A worker that also rewrites the same table takes
AccessExclusiveLock, and doing that on a schedule the user did not choose is a very
different proposition from doing it when they type it. This is the part I would
most want argued before any code: an extension that takes an exclusive lock on a
user's table on its own initiative needs a strong default of not doing so.
- Cost control. Autovacuum has
vacuum_cost_delay and friends precisely because
unbounded background I/O is worse than no background maintenance. We would need an
equivalent, and would need to respect the existing settings rather than invent
parallel ones.
- Registration cost. A background worker means
shared_preload_libraries becomes
effectively required for the feature, which changes installation. It should be
possible to run pgColumnar without it and lose only this.
- Failure behaviour. A worker that errors must not restart in a tight loop, and
must report where it failed in a way an administrator can act on.
Why a worker rather than the alternatives
- Documentation plus cron works today and is what we should keep recommending
until this exists. It is honest and it is what docs/administration.md should say.
- A
pg_cron dependency pushes the problem onto another extension and is not
available everywhere.
- Doing more inside the AM callback is tempting, since autovacuum already calls it,
but the callback runs under ShareUpdateExclusiveLock and the expensive operations
need AccessExclusiveLock. Escalating a lock inside a callback autovacuum invoked is
not something I would want to do.
That third option is worth re-examining anyway: some of what the functions do today may
be reachable under the weaker lock, which would shrink this issue rather than solve it.
Worth a look before committing to a daemon.
Scope
Nothing here is scheduled. The next step, whenever it is taken, is the measurement in
(1): what fraction of reclaimable space and clustering decay actually costs a query
enough to be worth an automatic rewrite. Until that number exists, any threshold is a
guess.
Related: #414 (custom analyze, gated on this), the lazy-versus-eager maintenance split
recorded in docs/limitations.md.
Future work, deliberately not scheduled. Filing it so the gap is recorded where it
is visible rather than discovered by a user, per #395.
The gap
pgColumnar has maintenance operations that PostgreSQL's own autovacuum daemon will
never invoke, because they are extension functions rather than table-AM callbacks:
pgcolumnar_relation_vacuum(visibility map, retire fully-deleted groups)pgcolumnar.vacuum()(the space-reclaiming rewrite)pgcolumnar.vacuum_sorted()/ clustering decaypgcolumnar.analyze()(#414)So the cheap online part is automatic and the expensive part is manual. A user who
never runs the functions accumulates reclaimable space and, if #414 goes ahead,
increasingly stale statistics.
The asymmetry matters: a table that is never rewritten wastes disk, which is visible
and survivable. Statistics that are never refreshed produce bad plans, which is
invisible and is felt as "the database got slower" with no obvious cause. That is the
argument for solving scheduling before adding more manual maintenance functions, and
it is why #414 is gated on this.
What it would be
A background worker registered from
_PG_init, in the shape of core's autovacuumlauncher: a launcher that wakes on an interval and starts per-database workers, each
deciding what needs attention and doing it.
The decisions that need answering first, none of which are code
collector. Our triggers are different in kind: reclaimable fraction (dead rows over
live), clustering decay (
pgcolumnar.sort_status, which already measures it), andstaleness for analyze. Each needs a threshold and a GUC, and thresholds invented
without measurement are how a daemon becomes a support burden.
the online work. A worker that also rewrites the same table takes
AccessExclusiveLock, and doing that on a schedule the user did not choose is a very
different proposition from doing it when they type it. This is the part I would
most want argued before any code: an extension that takes an exclusive lock on a
user's table on its own initiative needs a strong default of not doing so.
vacuum_cost_delayand friends precisely becauseunbounded background I/O is worse than no background maintenance. We would need an
equivalent, and would need to respect the existing settings rather than invent
parallel ones.
shared_preload_librariesbecomeseffectively required for the feature, which changes installation. It should be
possible to run pgColumnar without it and lose only this.
must report where it failed in a way an administrator can act on.
Why a worker rather than the alternatives
until this exists. It is honest and it is what
docs/administration.mdshould say.pg_crondependency pushes the problem onto another extension and is notavailable everywhere.
but the callback runs under ShareUpdateExclusiveLock and the expensive operations
need AccessExclusiveLock. Escalating a lock inside a callback autovacuum invoked is
not something I would want to do.
That third option is worth re-examining anyway: some of what the functions do today may
be reachable under the weaker lock, which would shrink this issue rather than solve it.
Worth a look before committing to a daemon.
Scope
Nothing here is scheduled. The next step, whenever it is taken, is the measurement in
(1): what fraction of reclaimable space and clustering decay actually costs a query
enough to be worth an automatic rewrite. Until that number exists, any threshold is a
guess.
Related: #414 (custom analyze, gated on this), the lazy-versus-eager maintenance split
recorded in
docs/limitations.md.