Postgres Vacuum in Function
From the documentation page:


  Tip: Plain VACUUM may not be satisfactory when a table contains large numbers of dead row versions as a result of massive update or delete activity. If you have such a table and you need to reclaim the excess disk space it occupies, you will need to use VACUUM FULL, or alternatively CLUSTER or one of the table-rewriting variants of ALTER TABLE. These commands rewrite an entire new copy of the table and build new indexes for it. All these options require exclusive lock. Note that they also temporarily use extra disk space approximately equal to the size of the table, since the old copies of the table and indexes can't be released until the new ones are complete.


If you can't get away with an exclusive lock on the table, you also might be fine with a simple ANALYZE &lt;tablename&gt;;, as that will only take a read lock and should update the statistics for the table and reduce ( if not entirely eliminate ) performance degradation for the other queries.  Then you can let the regular autovacuum daemon do its thing ( or whatever your current custom vacuum solution might be ) normally.

If your table doesn't even have a clustered index, you will first need to do an ALTER TABLE &lt;tablename&gt; CLUSTER ON &lt;indexname&gt;;.  You should probably have some kind of clustered index anyway: Having a massive heap table and poor performance against it often goes hand in hand.

As far as best practices go, I would be highly inclined to recommend the ANALYZE approach insofar as doing an automatic statistics update is by far preferable to an automatic index rebuild or virtually any form of VACUUM FULL being run without an admin actively watching it.