*** a/src/backend/commands/vacuumlazy.c --- b/src/backend/commands/vacuumlazy.c *************** *** 96,101 **** --- 96,108 ---- */ #define SKIP_PAGES_THRESHOLD ((BlockNumber) 32) + /* + * The following two values are used for identifying whether any table contains + * large number of unused rows and are eligible for 'VACUUM FULL'. + */ + #define RELPAGES_VALUES_THRESHOLD 1000 + #define FREESPACE_PERCENTAGE_THRESHOLD 0.5 + typedef struct LVRelStats { /* hasindex = true means two-pass strategy; false means one-pass */ *************** *** 155,161 **** static bool lazy_tid_reaped(ItemPointer itemptr, void *state); static int vac_cmp_itemptr(const void *left, const void *right); static bool heap_page_is_all_visible(Relation rel, Buffer buf, TransactionId *visibility_cutoff_xid); ! /* * lazy_vacuum_rel() -- perform LAZY VACUUM for one heap relation --- 162,168 ---- static int vac_cmp_itemptr(const void *left, const void *right); static bool heap_page_is_all_visible(Relation rel, Buffer buf, TransactionId *visibility_cutoff_xid); ! static bool check_needs_full_vacuum(Relation rel, LVRelStats *vacrelstats); /* * lazy_vacuum_rel() -- perform LAZY VACUUM for one heap relation *************** *** 364,369 **** lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, --- 371,412 ---- pg_rusage_show(&ru0)))); } } + + if (check_needs_full_vacuum(onerel, vacrelstats)) + ereport(LOG, + (errmsg("Table \"%s\" contains large numbers of unused row, suggest using VACUUM FULL on it!", + RelationGetRelationName(onerel)))); + } + + /* + * According the percentage of the free space in the table to check + * whether a table contains large numbers of unused row and are eligible for + * 'VACUUM FULL' + * + * Return: true -- need VACUUM FULL the table + */ + static bool + check_needs_full_vacuum(Relation rel, LVRelStats *vacrelstats) + { + bool ret = false; + BlockNumber i = 0; + Size total_freespace = 0; + + if (vacrelstats == NULL) + return false; + + if (vacrelstats->rel_pages > RELPAGES_VALUES_THRESHOLD) + { + for (i = 0; i < vacrelstats->rel_pages; i++) + { + total_freespace += GetRecordedFreeSpace(rel, i); + } + + if (total_freespace > vacrelstats->rel_pages * BLCKSZ * FREESPACE_PERCENTAGE_THRESHOLD) + ret = true; + } + + return ret; } /*