@ -112,8 +112,8 @@
typedef struct LVRelStats
{
/* has index = true means two-pass strategy; false means one-pass */
bool has index;
/* use index = true means two-pass strategy; false means one-pass */
bool use index;
/* Overall statistics about rel */
BlockNumber old_rel_pages ; /* previous value of pg_class.relpages */
BlockNumber rel_pages ; /* total number of pages */
@ -125,6 +125,8 @@ typedef struct LVRelStats
double new_rel_tuples ; /* new estimated total # of tuples */
double new_live_tuples ; /* new estimated total # of live tuples */
double new_dead_tuples ; /* new estimated total # of dead tuples */
double nleft_dead_tuples ; /* # of dead tuples we left */
double nleft_dead_itemids ; /* # of dead item pointers we left */
BlockNumber pages_removed ;
double tuples_deleted ;
BlockNumber nonempty_pages ; /* actually, last nonempty page + 1 */
@ -150,7 +152,7 @@ static BufferAccessStrategy vac_strategy;
/* non-export function prototypes */
static void lazy_scan_heap ( Relation onerel , int option s,
static void lazy_scan_heap ( Relation onerel , VacuumParams * param s,
LVRelStats * vacrelstats , Relation * Irel , int nindexes ,
bool aggressive ) ;
static void lazy_vacuum_heap ( Relation onerel , LVRelStats * vacrelstats , BlockNumber nblocks ) ;
@ -209,6 +211,7 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
MultiXactId new_min_multi ;
Assert ( params ! = NULL ) ;
Assert ( params - > index_cleanup ! = VACOPT_TERNARY_DEFAULT ) ;
/* measure elapsed time iff autovacuum logging requires it */
if ( IsAutoVacuumWorkerProcess ( ) & & params - > log_min_duration > = 0 )
@ -275,10 +278,11 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
/* Open all indexes of the relation */
vac_open_indexes ( onerel , RowExclusiveLock , & nindexes , & Irel ) ;
vacrelstats - > hasindex = ( nindexes > 0 ) ;
vacrelstats - > useindex = ( nindexes > 0 & &
params - > index_cleanup = = VACOPT_TERNARY_ENABLED ) ;
/* Do the vacuuming */
lazy_scan_heap ( onerel , params - > options , vacrelstats , Irel , nindexes , aggressive ) ;
lazy_scan_heap ( onerel , params , vacrelstats , Irel , nindexes , aggressive ) ;
/* Done with indexes */
vac_close_indexes ( nindexes , Irel , NoLock ) ;
@ -349,7 +353,7 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
new_rel_pages ,
new_live_tuples ,
new_rel_allvisible ,
vacrelstats - > hasindex ,
nindexes > 0 ,
new_frozen_xid ,
new_min_multi ,
false ) ;
@ -419,6 +423,12 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
vacrelstats - > new_rel_tuples ,
vacrelstats - > new_dead_tuples ,
OldestXmin ) ;
if ( vacrelstats - > nleft_dead_tuples > 0 | |
vacrelstats - > nleft_dead_itemids > 0 )
appendStringInfo ( & buf ,
_ ( " %.0f tuples and %.0f item identifiers are left as dead. \n " ) ,
vacrelstats - > nleft_dead_tuples ,
vacrelstats - > nleft_dead_itemids ) ;
appendStringInfo ( & buf ,
_ ( " buffer usage: %d hits, %d misses, %d dirtied \n " ) ,
VacuumPageHit ,
@ -485,7 +495,7 @@ vacuum_log_cleanup_info(Relation rel, LVRelStats *vacrelstats)
* reference them have been killed .
*/
static void
lazy_scan_heap ( Relation onerel , int option s, LVRelStats * vacrelstats ,
lazy_scan_heap ( Relation onerel , VacuumParams * param s, LVRelStats * vacrelstats ,
Relation * Irel , int nindexes , bool aggressive )
{
BlockNumber nblocks ,
@ -501,7 +511,10 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
live_tuples , /* live tuples (reltuples estimate) */
tups_vacuumed , /* tuples cleaned up by vacuum */
nkeep , /* dead-but-not-removable tuples */
nunused ; /* unused item pointers */
nunused , /* unused item pointers */
nleft_dead_tuples , /* tuples we left as dead */
nleft_dead_itemids ; /* item pointers we left as dead,
* includes nleft_dead_tuples . */
IndexBulkDeleteResult * * indstats ;
int i ;
PGRUsage ru0 ;
@ -534,6 +547,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
empty_pages = vacuumed_pages = 0 ;
next_fsm_block_to_vacuum = ( BlockNumber ) 0 ;
num_tuples = live_tuples = tups_vacuumed = nkeep = nunused = 0 ;
nleft_dead_itemids = nleft_dead_tuples = 0 ;
indstats = ( IndexBulkDeleteResult * * )
palloc0 ( nindexes * sizeof ( IndexBulkDeleteResult * ) ) ;
@ -599,7 +613,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
* be replayed on any hot standby , where it can be disruptive .
*/
next_unskippable_block = 0 ;
if ( ( options & VACOPT_DISABLE_PAGE_SKIPPING ) = = 0 )
if ( ( params - > options & VACOPT_DISABLE_PAGE_SKIPPING ) = = 0 )
{
while ( next_unskippable_block < nblocks )
{
@ -654,7 +668,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
{
/* Time to advance next_unskippable_block */
next_unskippable_block + + ;
if ( ( options & VACOPT_DISABLE_PAGE_SKIPPING ) = = 0 )
if ( ( params - > options & VACOPT_DISABLE_PAGE_SKIPPING ) = = 0 )
{
while ( next_unskippable_block < nblocks )
{
@ -1070,7 +1084,17 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
HeapTupleIsHeapOnly ( & tuple ) )
nkeep + = 1 ;
else
{
tupgone = true ; /* we can delete the tuple */
/*
* Since this dead tuple will not be vacuumed and
* ignored when index cleanup is disabled we count
* count it for reporting .
*/
if ( params - > index_cleanup = = VACOPT_TERNARY_ENABLED )
nleft_dead_tuples + + ;
}
all_visible = false ;
break ;
case HEAPTUPLE_LIVE :
@ -1222,15 +1246,33 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
}
/*
* If there are no indexes then we can vacuum the page right now
* instead of doing a second scan .
* If there are no indexes we can vacuum the page right now instead of
* doing a second scan . Also we don ' t do that but forget dead tuples
* when index cleanup is disabled .
*/
if ( nindexes = = 0 & &
vacrelstats - > num_dead_tuples > 0 )
if ( ! vacrelstats - > useindex & & vacrelstats - > num_dead_tuples > 0 )
{
/* Remove tuples from heap */
if ( nindexes = = 0 )
{
/* Remove tuples from heap if the table has no index */
lazy_vacuum_page ( onerel , blkno , buf , 0 , vacrelstats , & vmbuffer ) ;
vacuumed_pages + + ;
has_dead_tuples = false ;
}
else
{
/*
* Here , we have indexes but index cleanup is disabled . Instead of
* vacuuming the dead tuples on the heap , we just forget them .
*
* Note that vacrelstats - > dead_tuples could have tuples which
* became dead after HOT - pruning but are not marked dead yet .
* We do not process them because it ' s a very rare condition , and
* the next vacuum will process them anyway .
*/
Assert ( params - > index_cleanup = = VACOPT_TERNARY_DISABLED ) ;
nleft_dead_itemids + = vacrelstats - > num_dead_tuples ;
}
/*
* Forget the now - vacuumed tuples , and press on , but be careful
@ -1238,7 +1280,6 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
* valid .
*/
vacrelstats - > num_dead_tuples = 0 ;
vacuumed_pages + + ;
/*
* Periodically do incremental FSM vacuuming to make newly - freed
@ -1357,6 +1398,11 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
RecordPageWithFreeSpace ( onerel , blkno , freespace , nblocks ) ;
}
/* No dead tuples should be left if index cleanup is enabled */
Assert ( ( params - > index_cleanup = = VACOPT_TERNARY_ENABLED & &
nleft_dead_tuples = = 0 & & nleft_dead_itemids = = 0 ) | |
params - > index_cleanup = = VACOPT_TERNARY_DISABLED ) ;
/* report that everything is scanned and vacuumed */
pgstat_progress_update_param ( PROGRESS_VACUUM_HEAP_BLKS_SCANNED , blkno ) ;
@ -1364,7 +1410,9 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
/* save stats for use later */
vacrelstats - > tuples_deleted = tups_vacuumed ;
vacrelstats - > new_dead_tuples = nkeep ;
vacrelstats - > new_dead_tuples = nkeep + nleft_dead_tuples ;
vacrelstats - > nleft_dead_tuples = nleft_dead_tuples ;
vacrelstats - > nleft_dead_itemids = nleft_dead_itemids ;
/* now we can compute the new value for pg_class.reltuples */
vacrelstats - > new_live_tuples = vac_estimate_reltuples ( onerel ,
@ -1433,8 +1481,11 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
PROGRESS_VACUUM_PHASE_INDEX_CLEANUP ) ;
/* Do post-vacuum cleanup and statistics update for each index */
if ( vacrelstats - > useindex )
{
for ( i = 0 ; i < nindexes ; i + + )
lazy_cleanup_index ( Irel [ i ] , indstats [ i ] , vacrelstats ) ;
}
/* If no indexes, make log report that lazy_vacuum_heap would've made */
if ( vacuumed_pages )
@ -1465,6 +1516,8 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
" %u pages are entirely empty. \n " ,
empty_pages ) ,
empty_pages ) ;
appendStringInfo ( & buf , " %.0f tuples and %.0f item identifiers are left as dead. \n " ,
nleft_dead_tuples , nleft_dead_itemids ) ;
appendStringInfo ( & buf , _ ( " %s. " ) , pg_rusage_show ( & ru0 ) ) ;
ereport ( elevel ,
@ -2110,7 +2163,7 @@ lazy_space_alloc(LVRelStats *vacrelstats, BlockNumber relblocks)
autovacuum_work_mem ! = - 1 ?
autovacuum_work_mem : maintenance_work_mem ;
if ( vacrelstats - > has index)
if ( vacrelstats - > use index)
{
maxtuples = ( vac_work_mem * 1024L ) / sizeof ( ItemPointerData ) ;
maxtuples = Min ( maxtuples , INT_MAX ) ;