Auto-vacuuming should eventually get around to cleaning it up (assuming you haven't disabled it), but it may not be getting around to it soon enough for your purposes. There are many settings which can control auto-vacuuming and how/when it's done, which may be of interest: here and here.
This can be especially true of tables with high churn. That is, tables with lots of insertions and deletions. Long-running and idle transactions can also be a factor here, as MVCC will kick in and prevent the dead tuples from being reclaimed. The fact that manually doing a VACUUM
frees the dead tuples suggests that this isn't the case for you, though, and it may be the former issue instead.
In general, it's not recommended to do a VACUUM FULL
, as that takes out an exclusive table lock, particularly when most rows in a table have been updated/deleted.
From the doc:
The FULL option is not recommended for routine use, but might be
useful in special cases. An example is when you have deleted or
updated most of the rows in a table and would like the table to
physically shrink to occupy less disk space and allow faster table
scans. VACUUM FULL will usually shrink the table more than a plain
VACUUM would.
Is your usage pattern such that this would be the case? You did mention a "direct copy" was involved, but it's not clear exactly how that's being done.
I have had cases with high-churn tables where the default auto-vacuum rate just wasn't enough, and even relatively small amounts of dead tuples would greatly affect the query speed (this was in a large table which was queried very often and where the query needed to be extremely fast, and as such, was highly affected by dead tuples).
To help with this, I setup a manual VACUUM ANALYZE
of the table (so it will both free up the tuples and aid the query planner by updating the stats) in a cron job that was set to run every 5 minutes. Since there weren't that many dead tuples, the VACUUM
was pretty fast, and the constant vacuuming keeps the dead tuple count low enough so as to keep queries of that table fast.
Edit in response to comment from OP:
In the VACUUM doc, it says that:
VACUUM reclaims storage occupied by dead tuples
The doc then says that (emphasis mine):
VACUUM ANALYZE performs a VACUUM and then an ANALYZE for each selected
table. This is a handy combination form for routine maintenance
scripts. See ANALYZE for more details about its processing.
So it definitely reclaims dead tuples.
Best Answer
Vacuuming will not remove the existing bloat. It will free up that space for future use. Until that future use has happened, it will still look bloated.
To free it up now, you would have to do something drastic like
VACUUM FULL
,CLUSTER
, or use some external tool like pg_repack. That is a lot of churn to put your database through just to fix a problem that is not actually a problem.I would just do as @KookieMonster said, and increase the threshold. Then if things start to get worse, eventually you will start getting warnings again. (Actually, I wouldn't run check_postgres in the first place, but if I were, then...see above.)