Thread: Per-tablespace autovacuum settings

Per-tablespace autovacuum settings

From
Oleksii Kliukin
Date:
Hello,

Is there any interest in making autovacuum parameters available on a
tablespace level in order to apply those to all vacuumable objects in the
tablespace?

We have a set of tables running on ZFS, where autovacuum does almost no good
to us (except for preventing anti-wraparound) due to the nature of ZFS (FS
fragmentation caused by copy-on-write leads to sequential scans doing random
access) and the fact that our tables there are append-only. Initially, the
team in charge of the application just disabled autovacuum globally, but
that lead to a huge system catalog bloat.

At present, we have to re-enable autovacuum globally and then disable it
per-table using table storage parameters, but that is inelegant and requires
doing it once for existing tables and modifying the script that periodically
creates new ones (the whole system is a Postgres-based replacement of an
ElasticSearch cluster and we have to create new partitions regularly).

Grouping tables by tablespaces for the purpose of autovacuum configuration
seems natural, as tablespaces are often placed on another filesystems/device
that may require changing how often does autovacuum run, make it less/more
aggressive depending on the I/O performance or require disabling it
altogether as in my example above. Furthermore, given that we allow
cost-based options per-tablespace the infrastructure is already there and
the task is mostly to teach autovacuum to look at tablespaces in addition to
the relation storage options (in case of a conflict, relation options should
always take priority).


Regards,
Oleksii Kliukin



Re: Per-tablespace autovacuum settings

From
Andres Freund
Date:
Hi,

On 2019-02-14 17:56:17 +0100, Oleksii Kliukin wrote:
> Is there any interest in making autovacuum parameters available on a
> tablespace level in order to apply those to all vacuumable objects in the
> tablespace?
> 
> We have a set of tables running on ZFS, where autovacuum does almost no good
> to us (except for preventing anti-wraparound) due to the nature of ZFS (FS
> fragmentation caused by copy-on-write leads to sequential scans doing random
> access) and the fact that our tables there are append-only. Initially, the
> team in charge of the application just disabled autovacuum globally, but
> that lead to a huge system catalog bloat.
> 
> At present, we have to re-enable autovacuum globally and then disable it
> per-table using table storage parameters, but that is inelegant and requires
> doing it once for existing tables and modifying the script that periodically
> creates new ones (the whole system is a Postgres-based replacement of an
> ElasticSearch cluster and we have to create new partitions regularly).

Won't that a) lead to periodic massive anti-wraparound sessions? b)
prevent any use of index only scans?

ISTM you'd be better off running vacuum rarely, with large
thresholds. That way it'd do most of the writes in one pass, hopefully
leading to less fragementation, and it'd set the visibilitymap bits to
prevent further need to touch those. By doing it only rarely, vacuum
should process pages sequentially, reducing the fragmentation.


> Grouping tables by tablespaces for the purpose of autovacuum configuration
> seems natural, as tablespaces are often placed on another filesystems/device
> that may require changing how often does autovacuum run, make it less/more
> aggressive depending on the I/O performance or require disabling it
> altogether as in my example above. Furthermore, given that we allow
> cost-based options per-tablespace the infrastructure is already there and
> the task is mostly to teach autovacuum to look at tablespaces in addition to
> the relation storage options (in case of a conflict, relation options should
> always take priority).

While I don't buy the reasoning above, I think this'd be useful for
other cases.

Greetings,

Andres Freund


Re: Per-tablespace autovacuum settings

From
Tom Lane
Date:
Oleksii Kliukin <alexk@hintbits.com> writes:
> Is there any interest in making autovacuum parameters available on a
> tablespace level in order to apply those to all vacuumable objects in the
> tablespace?

I understand what you want to accomplish, and it doesn't seem
unreasonable.  But I just want to point out that the situation with
vacuuming parameters is on the edge of unintelligible already; adding
another scope might push it over the edge.  In particular there's no
principled way to decide whether an autovacuum parameter set at an outer
scope should override a plain-vacuum parameter set at a narrower scope.
And it's really questionable which of database-wide and tablespace-wide
should be seen as a narrower scope in the first place.

I don't know how to make this better, but I wish we'd take a step
back and think about it rather than just accreting more and more
complexity.

            regards, tom lane


Re: Per-tablespace autovacuum settings

From
Oleksii Kliukin
Date:
Andres Freund <andres@anarazel.de> wrote:

> Hi,
>
> On 2019-02-14 17:56:17 +0100, Oleksii Kliukin wrote:
>> Is there any interest in making autovacuum parameters available on a
>> tablespace level in order to apply those to all vacuumable objects in the
>> tablespace?
>>
>> We have a set of tables running on ZFS, where autovacuum does almost no good
>> to us (except for preventing anti-wraparound) due to the nature of ZFS (FS
>> fragmentation caused by copy-on-write leads to sequential scans doing random
>> access) and the fact that our tables there are append-only. Initially, the
>> team in charge of the application just disabled autovacuum globally, but
>> that lead to a huge system catalog bloat.
>>
>> At present, we have to re-enable autovacuum globally and then disable it
>> per-table using table storage parameters, but that is inelegant and requires
>> doing it once for existing tables and modifying the script that periodically
>> creates new ones (the whole system is a Postgres-based replacement of an
>> ElasticSearch cluster and we have to create new partitions regularly).
>
> Won't that a) lead to periodic massive anti-wraparound sessions? b)
> prevent any use of index only scans?

The wraparound is hardly an issue there, as the data is transient and only
exist for 14 days (I think the entire date-based partition is dropped,
that’s how we ended up with pg_class catalog bloat). The index-only scan can
be an issue, although, IIRC, there is some manual vacuum that runs from time
to time, perhaps following your advice below.

> ISTM you'd be better off running vacuum rarely, with large
> thresholds. That way it'd do most of the writes in one pass, hopefully
> leading to less fragementation, and it'd set the visibilitymap bits to
> prevent further need to touch those. By doing it only rarely, vacuum
> should process pages sequentially, reducing the fragmentation.
>
>
>> Grouping tables by tablespaces for the purpose of autovacuum configuration
>> seems natural, as tablespaces are often placed on another filesystems/device
>> that may require changing how often does autovacuum run, make it less/more
>> aggressive depending on the I/O performance or require disabling it
>> altogether as in my example above. Furthermore, given that we allow
>> cost-based options per-tablespace the infrastructure is already there and
>> the task is mostly to teach autovacuum to look at tablespaces in addition to
>> the relation storage options (in case of a conflict, relation options should
>> always take priority).
>
> While I don't buy the reasoning above, I think this'd be useful for
> other cases.

Even if we don’t want to disable autovacuum completely, we might want to
make it much less frequent by increasing the thresholds or costs/delays to
reduce the I/O strain for a particular tablespace.

Regards,
Oleksii Kliukin



Re: Per-tablespace autovacuum settings

From
Oleksii Kliukin
Date:
Tom Lane <tgl@sss.pgh.pa.us> wrote:

> Oleksii Kliukin <alexk@hintbits.com> writes:
>> Is there any interest in making autovacuum parameters available on a
>> tablespace level in order to apply those to all vacuumable objects in the
>> tablespace?
>
> I understand what you want to accomplish, and it doesn't seem
> unreasonable.  But I just want to point out that the situation with
> vacuuming parameters is on the edge of unintelligible already; adding
> another scope might push it over the edge.  In particular there's no
> principled way to decide whether an autovacuum parameter set at an outer
> scope should override a plain-vacuum parameter set at a narrower scope.

My naive understanding is that vacuum and autovacuum should decide
independently which scope applies, coming from the most specific (per-table
for autovacuum, per-DB for vacuum) to the broader scopes, ending with
configuration parameters at the outermost scope . Both *_cost_limit and
*_cost_delay should be taken from the current vacuum scope only if effective
autovacuum settings yield -1.

> And it's really questionable which of database-wide and tablespace-wide
> should be seen as a narrower scope in the first place.

AFAIK we don’t allow setting autovacuum options per-database; neither I
suggest enabling plain vacuum to be configured per-tablespace; as a result,
we won’t be deciding between databases and tablespaces, unless we want to do
cross-lookups from autovacuum to the outer scope of plain vacuum options
before considering autovacuum’s own outer scope and I don’t see any reason
to do that.

> I don't know how to make this better, but I wish we'd take a step
> back and think about it rather than just accreting more and more
> complexity.

I am willing to do the refactoring when necessary, any particular place in
the code that is indicative of the issue?

Regards,
Oleksii Kliukin



Re: Per-tablespace autovacuum settings

From
Oleksii Kliukin
Date:
Hello,

Oleksii Kliukin <alexk@hintbits.com> wrote:

> Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
>
>> I don't know how to make this better, but I wish we'd take a step
>> back and think about it rather than just accreting more and more
>> complexity.
>
> I am willing to do the refactoring when necessary, any particular place in
> the code that is indicative of the issue?

I’ve managed to return to that and here’s the first iteration of the patch
to add autovacuum parameters to tablespaces. I tried to make it as simple as
possible and didn’t make any decisions I found questionable, opting to
discuss them here instead. Some of them are probably linked to the kind of
issues mentioned by Tom upthread.

Things worth mentioning are:

- Fallbacks to autovacuum parameters in another scope. Right now in the
absence of the per-table and per-tablespace autovacuum parameters the code
uses the ones from the global scope. However, if only some of the reloptions
are set on a per-table level (i.e. none of the autovacuum related ones), we
assume defaults for the rest of reloptions without consulting the lower
level (i.e .per-tablespace options). This is so because we don’t have the
mechanism to tell whether the option is set to its default value (some of
them use -1 to request the fallback to the outer level, but for some it’s
not possible, i.e. autovacuum_enabled is just a boolean value).

- There are no separate per-tablespace settings for TOAST tables. I couldn't
find a strong case for setting all TOAST autovacuum options in a tablespace
to the same value that is distinct from the corresponding settings for the
regular tables. The difficulty of implementing TOAST options lies in the
fact that we strip the namespace part from the option name before storing it
in reltoptions. Changing that would break compatibility with previous
versions and require another step for pg_upgrade, I don’t think it is worth
the troubles. We could also come with a separate set of tablespace options,
i.e. prefixed with “toast_”, but that seems an ugly solution for the problem
that doesn’t seem real. As a result, if per-tablespace autovacuum options
are set and there are no table-specific TOAST options, the TOAST table will
inherit autovacuum options from the tablespace, rather than taking them from
the regular table it is attached to.

- There are a few relatively recently introduced options
(vacuum_index_cleanup, vacuum_truncate and
vacuum_cleanup_index_scale_factor) that I haven’t incorporated into the
per-tablespace options, as they are not part of autovacuum options and I see
no use for setting them on a tablespace level. This can be changed easily if
people think otherwise.

The patch is attached. It has a few tests and no documentation, I will
improvise both one we get in agreement on how the end result should look.


Kind regards,
Oleksii Kliukin




Attachment

Re: Per-tablespace autovacuum settings

From
Robert Haas
Date:
On Thu, Apr 25, 2019 at 12:36 PM Oleksii Kliukin <alexk@hintbits.com> wrote:
> - Fallbacks to autovacuum parameters in another scope. Right now in the
> absence of the per-table and per-tablespace autovacuum parameters the code
> uses the ones from the global scope. However, if only some of the reloptions
> are set on a per-table level (i.e. none of the autovacuum related ones), we
> assume defaults for the rest of reloptions without consulting the lower
> level (i.e .per-tablespace options). This is so because we don’t have the
> mechanism to tell whether the option is set to its default value (some of
> them use -1 to request the fallback to the outer level, but for some it’s
> not possible, i.e. autovacuum_enabled is just a boolean value).

That sounds like it's probably not acceptable?

--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: Per-tablespace autovacuum settings

From
Oleksii Kliukin
Date:
Robert Haas <robertmhaas@gmail.com> wrote:

> On Thu, Apr 25, 2019 at 12:36 PM Oleksii Kliukin <alexk@hintbits.com> wrote:
>> - Fallbacks to autovacuum parameters in another scope. Right now in the
>> absence of the per-table and per-tablespace autovacuum parameters the code
>> uses the ones from the global scope. However, if only some of the reloptions
>> are set on a per-table level (i.e. none of the autovacuum related ones), we
>> assume defaults for the rest of reloptions without consulting the lower
>> level (i.e .per-tablespace options). This is so because we don’t have the
>> mechanism to tell whether the option is set to its default value (some of
>> them use -1 to request the fallback to the outer level, but for some it’s
>> not possible, i.e. autovacuum_enabled is just a boolean value).
>
> That sounds like it's probably not acceptable?

Yes, I think it would be inconsistent. However, it looks like all the
options from AutoVacOpts other than autovacuum_enabled are set to -1 by
default. This can be used to tell whether the option is set to its default
value. For autovacuum_enabled we don’t care much: it’s true by default and
it’s a safe choice (even if the global autovacuum is off, enabling per-table
or per-tablespace one is a no-op).

I will update the patch.

Cheers,
Oleksii