@ -114,9 +114,9 @@ typedef struct LVRelStats
BlockNumber pinskipped_pages ; /* # of pages we skipped due to a pin */
BlockNumber frozenskipped_pages ; /* # of frozen pages we skipped */
BlockNumber tupcount_pages ; /* pages whose tuples we counted */
double scanned_tuples ; /* counts only tuples on tupcount_pages */
double old_rel_tuples ; /* previous value of pg_class.reltuples */
double old_live_tuples ; /* previous value of pg_class.reltuples */
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 */
BlockNumber pages_removed ;
double tuples_deleted ;
@ -196,7 +196,6 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
TransactionId xidFullScanLimit ;
MultiXactId mxactFullScanLimit ;
BlockNumber new_rel_pages ;
double new_rel_tuples ;
BlockNumber new_rel_allvisible ;
double new_live_tuples ;
TransactionId new_frozen_xid ;
@ -245,7 +244,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
vacrelstats = ( LVRelStats * ) palloc0 ( sizeof ( LVRelStats ) ) ;
vacrelstats - > old_rel_pages = onerel - > rd_rel - > relpages ;
vacrelstats - > old_rel _tuples = onerel - > rd_rel - > reltuples ;
vacrelstats - > old_live _tuples = onerel - > rd_rel - > reltuples ;
vacrelstats - > num_index_scans = 0 ;
vacrelstats - > pages_removed = 0 ;
vacrelstats - > lock_waiter_detected = false ;
@ -311,11 +310,11 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
* since then we don ' t know for certain that all tuples have a newer xmin .
*/
new_rel_pages = vacrelstats - > rel_pages ;
new_rel _tuples = vacrelstats - > new_rel _tuples ;
new_live _tuples = vacrelstats - > new_live _tuples ;
if ( vacrelstats - > tupcount_pages = = 0 & & new_rel_pages > 0 )
{
new_rel_pages = vacrelstats - > old_rel_pages ;
new_rel _tuples = vacrelstats - > old_rel _tuples ;
new_live _tuples = vacrelstats - > old_live _tuples ;
}
visibilitymap_count ( onerel , & new_rel_allvisible , NULL ) ;
@ -327,7 +326,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
vac_update_relstats ( onerel ,
new_rel_pages ,
new_rel _tuples ,
new_live _tuples ,
new_rel_allvisible ,
vacrelstats - > hasindex ,
new_frozen_xid ,
@ -335,10 +334,6 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
false ) ;
/* report results to the stats collector, too */
new_live_tuples = new_rel_tuples - vacrelstats - > new_dead_tuples ;
if ( new_live_tuples < 0 )
new_live_tuples = 0 ; /* just in case */
pgstat_report_vacuum ( RelationGetRelid ( onerel ) ,
onerel - > rd_rel - > relisshared ,
new_live_tuples ,
@ -471,10 +466,11 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
TransactionId relminmxid = onerel - > rd_rel - > relminmxid ;
BlockNumber empty_pages ,
vacuumed_pages ;
double num_tuples ,
tups_vacuumed ,
nkeep ,
nunused ;
double num_tuples , /* total number of nonremovable tuples */
live_tuples , /* live tuples (reltuples estimate) */
tups_vacuumed , /* tuples cleaned up by vacuum */
nkeep , /* dead-but-not-removable tuples */
nunused ; /* unused item pointers */
IndexBulkDeleteResult * * indstats ;
int i ;
PGRUsage ru0 ;
@ -505,7 +501,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
relname ) ) ) ;
empty_pages = vacuumed_pages = 0 ;
num_tuples = tups_vacuumed = nkeep = nunused = 0 ;
num_tuples = live_tuples = tups_vacuumed = nkeep = nunused = 0 ;
indstats = ( IndexBulkDeleteResult * * )
palloc0 ( nindexes * sizeof ( IndexBulkDeleteResult * ) ) ;
@ -988,6 +984,17 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
tupgone = false ;
/*
* The criteria for counting a tuple as live in this block need to
* match what analyze . c ' s acquire_sample_rows ( ) does , otherwise
* VACUUM and ANALYZE may produce wildly different reltuples
* values , e . g . when there are many recently - dead tuples .
*
* The logic here is a bit simpler than acquire_sample_rows ( ) , as
* VACUUM can ' t run inside a transaction block , which makes some
* cases impossible ( e . g . in - progress insert from the same
* transaction ) .
*/
switch ( HeapTupleSatisfiesVacuum ( & tuple , OldestXmin , buf ) )
{
case HEAPTUPLE_DEAD :
@ -1028,6 +1035,12 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
elog ( WARNING , " relation \" %s \" TID %u/%u: OID is invalid " ,
relname , blkno , offnum ) ;
/*
* Count it as live . Not only is this natural , but it ' s
* also what acquire_sample_rows ( ) does .
*/
live_tuples + = 1 ;
/*
* Is the tuple definitely visible to all transactions ?
*
@ -1073,12 +1086,29 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
all_visible = false ;
break ;
case HEAPTUPLE_INSERT_IN_PROGRESS :
/* This is an expected case during concurrent vacuum */
/*
* This is an expected case during concurrent vacuum .
*
* We do not count these rows as live , because we expect
* the inserting transaction to update the counters at
* commit , and we assume that will happen only after we
* report our results . This assumption is a bit shaky ,
* but it is what acquire_sample_rows ( ) does , so be
* consistent .
*/
all_visible = false ;
break ;
case HEAPTUPLE_DELETE_IN_PROGRESS :
/* This is an expected case during concurrent vacuum */
all_visible = false ;
/*
* Count such rows as live . As above , we assume the
* deleting transaction will commit and update the
* counters after we report .
*/
live_tuples + = 1 ;
break ;
default :
elog ( ERROR , " unexpected HeapTupleSatisfiesVacuum result " ) ;
@ -1281,15 +1311,18 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
pfree ( frozen ) ;
/* save stats for use later */
vacrelstats - > scanned_tuples = num_tuples ;
vacrelstats - > tuples_deleted = tups_vacuumed ;
vacrelstats - > new_dead_tuples = nkeep ;
/* now we can compute the new value for pg_class.reltuples */
vacrelstats - > new_rel_tuples = vac_estimate_reltuples ( onerel ,
nblocks ,
vacrelstats - > tupcount_pages ,
num_tuples ) ;
vacrelstats - > new_live_tuples = vac_estimate_reltuples ( onerel ,
nblocks ,
vacrelstats - > tupcount_pages ,
live_tuples ) ;
/* also compute total number of surviving heap entries */
vacrelstats - > new_rel_tuples =
vacrelstats - > new_live_tuples + vacrelstats - > new_dead_tuples ;
/*
* Release any remaining pin on visibility map page .
@ -1625,7 +1658,8 @@ lazy_vacuum_index(Relation indrel,
ivinfo . analyze_only = false ;
ivinfo . estimated_count = true ;
ivinfo . message_level = elevel ;
ivinfo . num_heap_tuples = vacrelstats - > old_rel_tuples ;
/* We can only provide an approximate value of num_heap_tuples here */
ivinfo . num_heap_tuples = vacrelstats - > old_live_tuples ;
ivinfo . strategy = vac_strategy ;
/* Do bulk deletion */
@ -1656,6 +1690,12 @@ lazy_cleanup_index(Relation indrel,
ivinfo . analyze_only = false ;
ivinfo . estimated_count = ( vacrelstats - > tupcount_pages < vacrelstats - > rel_pages ) ;
ivinfo . message_level = elevel ;
/*
* Now we can provide a better estimate of total number of surviving
* tuples ( we assume indexes are more interested in that than in the
* number of nominally live tuples ) .
*/
ivinfo . num_heap_tuples = vacrelstats - > new_rel_tuples ;
ivinfo . strategy = vac_strategy ;