How much time will a vacuum/autovacuum operation take?
On my PostgreSQL (8.3) I use this trick:
- I get table's disk size using
pg_total_relation_size()
- this includes indexes and TOAST size, which is whatVACUUM
processes. This gives me the idea of how many bytes theVACUUM
has to read. - I run
VACUUM
on the table. - I find the
pid
of theVACUUM
process (inpg_catalog.pg_stat_activity
). - In Linux shell I run
while true; do cat /proc/123/io | grep read_bytes; sleep 60; done
(where123
is the pid) - this shows me bytes read by the process from the disk so far.
This gives me rough idea on how many bytes are processed (read) every minute by the VACUUM
. I presume that the VACUUM
must read through the whole table (including indexes and TOAST), whose disk size I know from the step 1.
I presume that the table is large enough so that the majority of it's pages must be read from disk (they are not present in Postgres shared memory), so the read_bytes
field is good enough to be used as a progress counter.
Everytime I did this, the total bytes read by the process was no more than 5% from the total relation size, so I guess this approach may be good enough for You.
This is very hard to determine. You can tune autovacuuming to be more agressive or to be milder. But when set to mild and it is lagging behind and the base I/O load is too high, it can happen that it never reaches a proper vacuumed state - then you see the process running and running and running. Furthermore, later PostreSQL editions have much improved autovacuum capabilities, this alone may be enough to move to one of them (preferably 9.2 as the most recent one).
The progress bar sounds a good idea but I imagine it is not that easy to implement meaningfully. As you have constant load on your tables it is quite possible that the progress is apparently going backwards (I mean that the dead row count/percentage increases instead of decreasing) - then what conclusion do you draw?
I found this post and this post helpful, but like others have mentioned, it can be difficult to calculate the overall progress of vacuum, since the process involves a few separate operations.
I use this query to monitor the progress of vacuum's table scanning, which seems to be the bulk of the work:
SELECT heap_blks_scanned/cast(heap_blks_total as numeric)*100 as heap_blks_percent, progress.*, activity.query
FROM pg_stat_progress_vacuum AS progress
INNER JOIN pg_stat_activity AS activity ON activity.pid = progress.pid;
However, this won't include the index scanning, which happens afterwards, and can take just as long, if not longer, if you have a ton of indexes. Unfortunately, I can find no way to monitor index scanning/vacuuming.