8

I've found a query to view when vacuums have run, but not which are currently running. (http://heatware.net/databases/postgres-tables-auto-vacuum-analyze/)

Is there a query to accomplish this? I know I can hit pg_stat_activity, but some vacuums don't have the table name, but rather have pg_toast.pg_toast_3621837, so this wouldn't work 100% of the time.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Geesu
  • 5,928
  • 11
  • 43
  • 72
  • I believe you can find the answer to your question here: http://stackoverflow.com/questions/18456026/postgres-pg-toast-in-autovacuum-which-table – Zeki Jul 01 '14 at 21:46
  • I'm not aware of anything simple / canned. Zeki linked to a way to tell which base table a toast table is associated with. I'm curious though ... why? What're you trying to accomplish with this? – Craig Ringer Jul 02 '14 at 00:49
  • I have large rake task in my rails project that I don't want to kick off while a vacuum is running. The query takes a couple hours to run and the database load increases dramatically if a vacuum is running. – Geesu Jul 02 '14 at 13:15

2 Answers2

6

This problem can easily be solved with system catalogs. I suggest to join on pg_locks since autovacuum acquires a ShareUpdateExclusiveLock lock on the table it is working on, to avoid some manual parsing of the query from pg_stat_activity.

The following query lists the tables being auto-vacuumed, solving the pg_toast reference if a toast table is being vacuumed, as explained in Postgres pg_toast in autovacuum - which table? question linked to by @Zeki.

SELECT n.nspname || '.' || c.relname
    FROM pg_namespace n, pg_stat_activity a, pg_locks l, pg_class c
    WHERE
        a.query LIKE 'autovacuum: %'
        AND l.pid = a.pid
        AND l.mode = 'ShareUpdateExclusiveLock'
        AND (c.oid = l.relation OR c.reltoastrelid = l.relation)
        AND n.oid = c.relnamespace
        AND n.nspname <> 'pg_toast';

Please note that while pg_stat_activity and pg_locks catalogs are shared across databases, this query will only list the tables being auto-vacuumed in the current database as pg_relation is not a shared catalog.

Community
  • 1
  • 1
Paul Guyot
  • 6,257
  • 1
  • 20
  • 31
2

In instead of finding if the tables are being vacuumed turn auto vacuum off for the involved tables:

alter table table_name_pattern 
set (
    autovacuum_enabled = false,
    toast.autovacuum_enabled = false
);

table pattern is a glob pattern like tbl*. At the end of the query turn auto vacuum back on

alter table table_name_pattern 
set (
    autovacuum_enabled = true,
    toast.autovacuum_enabled = true
);

Edit in response to the commentaries:

The query to find if the involved tables are being vacuumed is unnecessary and useless. If it is known that one or more of the involved tables are being vacuumed what is it supposed to be done? Wait and keep repeating the inquiring query until none is being vacuumed? And when none is then start the long query just to discover after a while that auto vacuum was just kicked off again? There is no point. Why not just turn auto vacuum off and avoid all the hassle?

There is no ethical superiority in doing it the hard way, especially if the hard way is going to give worse results than the simple one. Simpler code is simpler to use and understand but it is not necessarily easier to build. Many times it is the opposite, requiring more intellectual effort or preparedness then the complex one.


If the autovacuum setting is altered inside a transaction and that transaction is rolled back the setting will be back to whatever it was before the transaction start

drop table if exists t;
create table t (id int);

begin;

alter table t
set (
    autovacuum_enabled = false,
    toast.autovacuum_enabled = false
);

\d+ t
                          Table "public.t"
 Column |  Type   | Modifiers | Storage | Stats target | Description 
--------+---------+-----------+---------+--------------+-------------
 id     | integer |           | plain   |              | 
Has OIDs: no
Options: autovacuum_enabled=false

rollback;

\d+ t
                          Table "public.t"
 Column |  Type   | Modifiers | Storage | Stats target | Description 
--------+---------+-----------+---------+--------------+-------------
 id     | integer |           | plain   |              | 
Has OIDs: no

But that setting inside the transaction will not be seen outside of the transaction so I guess autovacuum will still run. If this is true than the setting must be done outside of the transaction and controlled by a job that will turn it back regardless of what happens with the long running query.

Clodoaldo Neto
  • 118,695
  • 26
  • 233
  • 260
  • This is a helpful answer in some situations, so I upvoted it. It doesn't actually answer the question as it was asked, so I'm not giving it the bounty. – Kirk Roybal Jul 03 '14 at 21:30
  • @Kirk It does not answer the question as asked, but it solves the problem as explicated in the commentaries. Thanks for the upvote anyway. – Clodoaldo Neto Jul 03 '14 at 21:33
  • The bounty is there to encourage somebody to do the work of writing the "hard" query. Your answer is helpful and appreciated, but misses the point of the bounty. Maybe @Geesu will accept your answer because it applies to him. – Kirk Roybal Jul 03 '14 at 21:36
  • @Kirk Edited in attention to your comments. – Clodoaldo Neto Jul 03 '14 at 22:09
  • "unnecessary and useless"... that is a matter of opinion. Do you really know every possible circumstance and are ready to say that no one could possibly have a use case that you haven't thought about? If that's true, I suggest you go on over to the Ubuntu forums and write "RTFM" and "you don't need that" answers all you want. Those answers are inappropriate on SO. " no ethical superiority" ... That is a personal comment and an assumption of character that also has no place on SO. – Kirk Roybal Jul 03 '14 at 22:15
  • "what is it supposed to be done..." is the only valid question you ask. The answer to that question is "wait". Yes, it is possible that the vacuum will kick in immediately or even as a response to the activity. In the interim, a useful transaction may be accomplished that isn't blocked. Or a parallel process may use the query to figure out if the work process is being slowed down. In a 24/7 environment, sometimes you have to make compromises, and shutting off autovacuum isn't *always* the right judgement call, although I agree that most of the time your answer is appropriate. (upvoted). – Kirk Roybal Jul 03 '14 at 22:25
  • I wonder, will turning the autovacuum off have the expected effect inside a transaction? E.g. BEGIN, set (autovacuum_enabled = false), work ... set (autovacuum_enabled = true), COMMIT? If yes, cool. If not, then I'd say turning autovacuum off is dangerous, something may happen and the autovacuum will stay off... – ArtemGr Jul 05 '14 at 13:51
  • @ArtemGr Update about altering the autovacuum setting inside a transaction. – Clodoaldo Neto Jul 05 '14 at 14:13
  • I like this idea - will disabling the auto vacuum stop existing ones? This solves my problem much better than constantly checking if it is running, if so. – Geesu Jul 05 '14 at 16:39