Improve the IndexVacuumInfo/IndexBulkDeleteResult API to allow somewhat sane
behavior in cases where we don't know the heap tuple count accurately; in particular partial vacuum, but this also makes the API a bit more useful for ANALYZE. This patch adds "estimated_count" flags to both structs so that an approximate count can be flagged as such, and adjusts the logic so that approximate counts are not used for updating pg_class.reltuples. This fixes my previous complaint that VACUUM was putting ridiculous values into pg_class.reltuples for indexes. The actual impact of that bug is limited, because the planner only pays attention to reltuples for an index if the index is partial; which probably explains why beta testers hadn't noticed a degradation in plan quality from it. But it needs to be fixed. The whole thing is a bit messy and should be redesigned in future, because reltuples now has the potential to drift quite far away from reality when a long period elapses with no non-partial vacuums. But this is as good as it's going to get for 8.4.
This commit is contained in:
parent
4334695b30
commit
32ea236361
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.28 2009/03/24 20:17:11 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.29 2009/06/06 22:13:50 tgl Exp $
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -741,6 +741,7 @@ ginvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
* tell how many distinct heap entries are referenced by a GIN index.
|
* tell how many distinct heap entries are referenced by a GIN index.
|
||||||
*/
|
*/
|
||||||
stats->num_index_tuples = info->num_heap_tuples;
|
stats->num_index_tuples = info->num_heap_tuples;
|
||||||
|
stats->estimated_count = info->estimated_count;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If vacuum full, we already have exclusive lock on the index. Otherwise,
|
* If vacuum full, we already have exclusive lock on the index. Otherwise,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.43 2009/03/24 20:17:11 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/gist/gistvacuum.c,v 1.44 2009/06/06 22:13:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -524,8 +524,8 @@ gistvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
stats = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
|
stats = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
|
||||||
/* use heap's tuple count */
|
/* use heap's tuple count */
|
||||||
Assert(info->num_heap_tuples >= 0);
|
|
||||||
stats->std.num_index_tuples = info->num_heap_tuples;
|
stats->std.num_index_tuples = info->num_heap_tuples;
|
||||||
|
stats->std.estimated_count = info->estimated_count;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX the above is wrong if index is partial. Would it be OK to just
|
* XXX the above is wrong if index is partial. Would it be OK to just
|
||||||
@ -679,6 +679,7 @@ gistbulkdelete(PG_FUNCTION_ARGS)
|
|||||||
if (stats == NULL)
|
if (stats == NULL)
|
||||||
stats = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
|
stats = (GistBulkDeleteResult *) palloc0(sizeof(GistBulkDeleteResult));
|
||||||
/* we'll re-count the tuples each time */
|
/* we'll re-count the tuples each time */
|
||||||
|
stats->std.estimated_count = false;
|
||||||
stats->std.num_index_tuples = 0;
|
stats->std.num_index_tuples = 0;
|
||||||
|
|
||||||
stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
|
stack = (GistBDItem *) palloc0(sizeof(GistBDItem));
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.110 2009/05/05 19:36:32 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.111 2009/06/06 22:13:50 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* This file contains only the public interface routines.
|
* This file contains only the public interface routines.
|
||||||
@ -610,6 +610,8 @@ loop_top:
|
|||||||
/*
|
/*
|
||||||
* Otherwise, our count is untrustworthy since we may have
|
* Otherwise, our count is untrustworthy since we may have
|
||||||
* double-scanned tuples in split buckets. Proceed by dead-reckoning.
|
* double-scanned tuples in split buckets. Proceed by dead-reckoning.
|
||||||
|
* (Note: we still return estimated_count = false, because using this
|
||||||
|
* count is better than not updating reltuples at all.)
|
||||||
*/
|
*/
|
||||||
if (metap->hashm_ntuples > tuples_removed)
|
if (metap->hashm_ntuples > tuples_removed)
|
||||||
metap->hashm_ntuples -= tuples_removed;
|
metap->hashm_ntuples -= tuples_removed;
|
||||||
@ -623,6 +625,7 @@ loop_top:
|
|||||||
/* return statistics */
|
/* return statistics */
|
||||||
if (stats == NULL)
|
if (stats == NULL)
|
||||||
stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
stats = (IndexBulkDeleteResult *) palloc0(sizeof(IndexBulkDeleteResult));
|
||||||
|
stats->estimated_count = false;
|
||||||
stats->num_index_tuples = num_index_tuples;
|
stats->num_index_tuples = num_index_tuples;
|
||||||
stats->tuples_removed += tuples_removed;
|
stats->tuples_removed += tuples_removed;
|
||||||
/* hashvacuumcleanup will fill in num_pages */
|
/* hashvacuumcleanup will fill in num_pages */
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.169 2009/05/05 19:36:32 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.170 2009/06/06 22:13:51 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -579,10 +579,11 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
|
|||||||
/*
|
/*
|
||||||
* During a non-FULL vacuum it's quite possible for us to be fooled by
|
* During a non-FULL vacuum it's quite possible for us to be fooled by
|
||||||
* concurrent page splits into double-counting some index tuples, so
|
* concurrent page splits into double-counting some index tuples, so
|
||||||
* disbelieve any total that exceeds the underlying heap's count. (We
|
* disbelieve any total that exceeds the underlying heap's count ...
|
||||||
* can't check this during btbulkdelete.)
|
* if we know that accurately. Otherwise this might just make matters
|
||||||
|
* worse.
|
||||||
*/
|
*/
|
||||||
if (!info->vacuum_full)
|
if (!info->vacuum_full && !info->estimated_count)
|
||||||
{
|
{
|
||||||
if (stats->num_index_tuples > info->num_heap_tuples)
|
if (stats->num_index_tuples > info->num_heap_tuples)
|
||||||
stats->num_index_tuples = info->num_heap_tuples;
|
stats->num_index_tuples = info->num_heap_tuples;
|
||||||
@ -618,6 +619,7 @@ btvacuumscan(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
|
|||||||
* Reset counts that will be incremented during the scan; needed in case
|
* Reset counts that will be incremented during the scan; needed in case
|
||||||
* of multiple scans during a single VACUUM command
|
* of multiple scans during a single VACUUM command
|
||||||
*/
|
*/
|
||||||
|
stats->estimated_count = false;
|
||||||
stats->num_index_tuples = 0;
|
stats->num_index_tuples = 0;
|
||||||
stats->pages_deleted = 0;
|
stats->pages_deleted = 0;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.316 2009/05/31 20:55:37 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.317 2009/06/06 22:13:51 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -1938,8 +1938,9 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
|
|||||||
ivinfo.index = indexRelation;
|
ivinfo.index = indexRelation;
|
||||||
ivinfo.vacuum_full = false;
|
ivinfo.vacuum_full = false;
|
||||||
ivinfo.analyze_only = false;
|
ivinfo.analyze_only = false;
|
||||||
|
ivinfo.estimated_count = true;
|
||||||
ivinfo.message_level = DEBUG2;
|
ivinfo.message_level = DEBUG2;
|
||||||
ivinfo.num_heap_tuples = -1;
|
ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
|
||||||
ivinfo.strategy = NULL;
|
ivinfo.strategy = NULL;
|
||||||
|
|
||||||
state.tuplesort = tuplesort_begin_datum(TIDOID,
|
state.tuplesort = tuplesort_begin_datum(TIDOID,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.137 2009/05/19 08:30:00 heikki Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.138 2009/06/06 22:13:51 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -498,8 +498,9 @@ cleanup:
|
|||||||
ivinfo.index = Irel[ind];
|
ivinfo.index = Irel[ind];
|
||||||
ivinfo.vacuum_full = false;
|
ivinfo.vacuum_full = false;
|
||||||
ivinfo.analyze_only = true;
|
ivinfo.analyze_only = true;
|
||||||
|
ivinfo.estimated_count = true;
|
||||||
ivinfo.message_level = elevel;
|
ivinfo.message_level = elevel;
|
||||||
ivinfo.num_heap_tuples = -1; /* not known for sure */
|
ivinfo.num_heap_tuples = onerel->rd_rel->reltuples;
|
||||||
ivinfo.strategy = vac_strategy;
|
ivinfo.strategy = vac_strategy;
|
||||||
|
|
||||||
stats = index_vacuum_cleanup(&ivinfo, NULL);
|
stats = index_vacuum_cleanup(&ivinfo, NULL);
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.387 2009/03/31 22:12:48 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.388 2009/06/06 22:13:51 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -3389,6 +3389,7 @@ scan_index(Relation indrel, double num_tuples)
|
|||||||
ivinfo.index = indrel;
|
ivinfo.index = indrel;
|
||||||
ivinfo.vacuum_full = true;
|
ivinfo.vacuum_full = true;
|
||||||
ivinfo.analyze_only = false;
|
ivinfo.analyze_only = false;
|
||||||
|
ivinfo.estimated_count = false;
|
||||||
ivinfo.message_level = elevel;
|
ivinfo.message_level = elevel;
|
||||||
ivinfo.num_heap_tuples = num_tuples;
|
ivinfo.num_heap_tuples = num_tuples;
|
||||||
ivinfo.strategy = vac_strategy;
|
ivinfo.strategy = vac_strategy;
|
||||||
@ -3398,10 +3399,14 @@ scan_index(Relation indrel, double num_tuples)
|
|||||||
if (!stats)
|
if (!stats)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* now update statistics in pg_class */
|
/*
|
||||||
vac_update_relstats(indrel,
|
* Now update statistics in pg_class, but only if the index says the
|
||||||
stats->num_pages, stats->num_index_tuples,
|
* count is accurate.
|
||||||
false, InvalidTransactionId);
|
*/
|
||||||
|
if (!stats->estimated_count)
|
||||||
|
vac_update_relstats(indrel,
|
||||||
|
stats->num_pages, stats->num_index_tuples,
|
||||||
|
false, InvalidTransactionId);
|
||||||
|
|
||||||
ereport(elevel,
|
ereport(elevel,
|
||||||
(errmsg("index \"%s\" now contains %.0f row versions in %u pages",
|
(errmsg("index \"%s\" now contains %.0f row versions in %u pages",
|
||||||
@ -3417,7 +3422,8 @@ scan_index(Relation indrel, double num_tuples)
|
|||||||
* Check for tuple count mismatch. If the index is partial, then it's OK
|
* Check for tuple count mismatch. If the index is partial, then it's OK
|
||||||
* for it to have fewer tuples than the heap; else we got trouble.
|
* for it to have fewer tuples than the heap; else we got trouble.
|
||||||
*/
|
*/
|
||||||
if (stats->num_index_tuples != num_tuples)
|
if (!stats->estimated_count &&
|
||||||
|
stats->num_index_tuples != num_tuples)
|
||||||
{
|
{
|
||||||
if (stats->num_index_tuples > num_tuples ||
|
if (stats->num_index_tuples > num_tuples ||
|
||||||
!vac_is_partial_index(indrel))
|
!vac_is_partial_index(indrel))
|
||||||
@ -3456,6 +3462,7 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
|
|||||||
ivinfo.index = indrel;
|
ivinfo.index = indrel;
|
||||||
ivinfo.vacuum_full = true;
|
ivinfo.vacuum_full = true;
|
||||||
ivinfo.analyze_only = false;
|
ivinfo.analyze_only = false;
|
||||||
|
ivinfo.estimated_count = false;
|
||||||
ivinfo.message_level = elevel;
|
ivinfo.message_level = elevel;
|
||||||
ivinfo.num_heap_tuples = num_tuples + keep_tuples;
|
ivinfo.num_heap_tuples = num_tuples + keep_tuples;
|
||||||
ivinfo.strategy = vac_strategy;
|
ivinfo.strategy = vac_strategy;
|
||||||
@ -3469,10 +3476,14 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
|
|||||||
if (!stats)
|
if (!stats)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* now update statistics in pg_class */
|
/*
|
||||||
vac_update_relstats(indrel,
|
* Now update statistics in pg_class, but only if the index says the
|
||||||
stats->num_pages, stats->num_index_tuples,
|
* count is accurate.
|
||||||
false, InvalidTransactionId);
|
*/
|
||||||
|
if (!stats->estimated_count)
|
||||||
|
vac_update_relstats(indrel,
|
||||||
|
stats->num_pages, stats->num_index_tuples,
|
||||||
|
false, InvalidTransactionId);
|
||||||
|
|
||||||
ereport(elevel,
|
ereport(elevel,
|
||||||
(errmsg("index \"%s\" now contains %.0f row versions in %u pages",
|
(errmsg("index \"%s\" now contains %.0f row versions in %u pages",
|
||||||
@ -3490,7 +3501,8 @@ vacuum_index(VacPageList vacpagelist, Relation indrel,
|
|||||||
* Check for tuple count mismatch. If the index is partial, then it's OK
|
* Check for tuple count mismatch. If the index is partial, then it's OK
|
||||||
* for it to have fewer tuples than the heap; else we got trouble.
|
* for it to have fewer tuples than the heap; else we got trouble.
|
||||||
*/
|
*/
|
||||||
if (stats->num_index_tuples != num_tuples + keep_tuples)
|
if (!stats->estimated_count &&
|
||||||
|
stats->num_index_tuples != num_tuples + keep_tuples)
|
||||||
{
|
{
|
||||||
if (stats->num_index_tuples > num_tuples + keep_tuples ||
|
if (stats->num_index_tuples > num_tuples + keep_tuples ||
|
||||||
!vac_is_partial_index(indrel))
|
!vac_is_partial_index(indrel))
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.119 2009/03/24 20:17:14 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.120 2009/06/06 22:13:51 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -84,9 +84,11 @@ typedef struct LVRelStats
|
|||||||
{
|
{
|
||||||
/* hasindex = true means two-pass strategy; false means one-pass */
|
/* hasindex = true means two-pass strategy; false means one-pass */
|
||||||
bool hasindex;
|
bool hasindex;
|
||||||
|
bool scanned_all; /* have we scanned all pages (this far)? */
|
||||||
/* Overall statistics about rel */
|
/* Overall statistics about rel */
|
||||||
BlockNumber rel_pages;
|
BlockNumber rel_pages;
|
||||||
double rel_tuples;
|
double old_rel_tuples; /* previous value of pg_class.reltuples */
|
||||||
|
double rel_tuples; /* counts only tuples on scanned pages */
|
||||||
BlockNumber pages_removed;
|
BlockNumber pages_removed;
|
||||||
double tuples_deleted;
|
double tuples_deleted;
|
||||||
BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */
|
BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */
|
||||||
@ -96,7 +98,6 @@ typedef struct LVRelStats
|
|||||||
int max_dead_tuples; /* # slots allocated in array */
|
int max_dead_tuples; /* # slots allocated in array */
|
||||||
ItemPointer dead_tuples; /* array of ItemPointerData */
|
ItemPointer dead_tuples; /* array of ItemPointerData */
|
||||||
int num_index_scans;
|
int num_index_scans;
|
||||||
bool scanned_all; /* have we scanned all pages (this far)? */
|
|
||||||
} LVRelStats;
|
} LVRelStats;
|
||||||
|
|
||||||
|
|
||||||
@ -174,8 +175,9 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
|
|||||||
|
|
||||||
vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats));
|
vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats));
|
||||||
|
|
||||||
vacrelstats->num_index_scans = 0;
|
|
||||||
vacrelstats->scanned_all = true; /* will be cleared if we skip a page */
|
vacrelstats->scanned_all = true; /* will be cleared if we skip a page */
|
||||||
|
vacrelstats->old_rel_tuples = onerel->rd_rel->reltuples;
|
||||||
|
vacrelstats->num_index_scans = 0;
|
||||||
|
|
||||||
/* Open all indexes of the relation */
|
/* Open all indexes of the relation */
|
||||||
vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel);
|
vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel);
|
||||||
@ -876,9 +878,9 @@ lazy_vacuum_index(Relation indrel,
|
|||||||
ivinfo.index = indrel;
|
ivinfo.index = indrel;
|
||||||
ivinfo.vacuum_full = false;
|
ivinfo.vacuum_full = false;
|
||||||
ivinfo.analyze_only = false;
|
ivinfo.analyze_only = false;
|
||||||
|
ivinfo.estimated_count = true;
|
||||||
ivinfo.message_level = elevel;
|
ivinfo.message_level = elevel;
|
||||||
/* We don't yet know rel_tuples, so pass -1 */
|
ivinfo.num_heap_tuples = vacrelstats->old_rel_tuples;
|
||||||
ivinfo.num_heap_tuples = -1;
|
|
||||||
ivinfo.strategy = vac_strategy;
|
ivinfo.strategy = vac_strategy;
|
||||||
|
|
||||||
/* Do bulk deletion */
|
/* Do bulk deletion */
|
||||||
@ -908,8 +910,10 @@ lazy_cleanup_index(Relation indrel,
|
|||||||
ivinfo.index = indrel;
|
ivinfo.index = indrel;
|
||||||
ivinfo.vacuum_full = false;
|
ivinfo.vacuum_full = false;
|
||||||
ivinfo.analyze_only = false;
|
ivinfo.analyze_only = false;
|
||||||
|
ivinfo.estimated_count = !vacrelstats->scanned_all;
|
||||||
ivinfo.message_level = elevel;
|
ivinfo.message_level = elevel;
|
||||||
ivinfo.num_heap_tuples = vacrelstats->rel_tuples;
|
/* use rel_tuples only if we scanned all pages, else fall back */
|
||||||
|
ivinfo.num_heap_tuples = vacrelstats->scanned_all ? vacrelstats->rel_tuples : vacrelstats->old_rel_tuples;
|
||||||
ivinfo.strategy = vac_strategy;
|
ivinfo.strategy = vac_strategy;
|
||||||
|
|
||||||
stats = index_vacuum_cleanup(&ivinfo, stats);
|
stats = index_vacuum_cleanup(&ivinfo, stats);
|
||||||
@ -917,10 +921,14 @@ lazy_cleanup_index(Relation indrel,
|
|||||||
if (!stats)
|
if (!stats)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* now update statistics in pg_class */
|
/*
|
||||||
vac_update_relstats(indrel,
|
* Now update statistics in pg_class, but only if the index says the
|
||||||
stats->num_pages, stats->num_index_tuples,
|
* count is accurate.
|
||||||
false, InvalidTransactionId);
|
*/
|
||||||
|
if (!stats->estimated_count)
|
||||||
|
vac_update_relstats(indrel,
|
||||||
|
stats->num_pages, stats->num_index_tuples,
|
||||||
|
false, InvalidTransactionId);
|
||||||
|
|
||||||
ereport(elevel,
|
ereport(elevel,
|
||||||
(errmsg("index \"%s\" now contains %.0f row versions in %u pages",
|
(errmsg("index \"%s\" now contains %.0f row versions in %u pages",
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright (c) 2001-2009, PostgreSQL Global Development Group
|
* Copyright (c) 2001-2009, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.187 2009/01/01 17:23:46 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.188 2009/06/06 22:13:51 tgl Exp $
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
@ -3774,6 +3774,13 @@ pgstat_recv_vacuum(PgStat_MsgVacuum *msg, int len)
|
|||||||
{
|
{
|
||||||
if (msg->m_scanned_all)
|
if (msg->m_scanned_all)
|
||||||
tabentry->last_anl_tuples = msg->m_tuples;
|
tabentry->last_anl_tuples = msg->m_tuples;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* last_anl_tuples must never exceed n_live_tuples+n_dead_tuples */
|
||||||
|
tabentry->last_anl_tuples = Min(tabentry->last_anl_tuples,
|
||||||
|
tabentry->n_live_tuples);
|
||||||
|
}
|
||||||
|
|
||||||
if (msg->m_autovacuum)
|
if (msg->m_autovacuum)
|
||||||
tabentry->autovac_analyze_timestamp = msg->m_vacuumtime;
|
tabentry->autovac_analyze_timestamp = msg->m_vacuumtime;
|
||||||
else
|
else
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.76 2009/03/24 20:17:14 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/access/genam.h,v 1.77 2009/06/06 22:13:52 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -34,14 +34,17 @@ typedef struct IndexBuildResult
|
|||||||
/*
|
/*
|
||||||
* Struct for input arguments passed to ambulkdelete and amvacuumcleanup
|
* Struct for input arguments passed to ambulkdelete and amvacuumcleanup
|
||||||
*
|
*
|
||||||
* Note that num_heap_tuples will not be valid during ambulkdelete,
|
* num_heap_tuples is accurate only when estimated_count is false;
|
||||||
* only amvacuumcleanup.
|
* otherwise it's just an estimate (currently, the estimate is the
|
||||||
|
* prior value of the relation's pg_class.reltuples field). It will
|
||||||
|
* always just be an estimate during ambulkdelete.
|
||||||
*/
|
*/
|
||||||
typedef struct IndexVacuumInfo
|
typedef struct IndexVacuumInfo
|
||||||
{
|
{
|
||||||
Relation index; /* the index being vacuumed */
|
Relation index; /* the index being vacuumed */
|
||||||
bool vacuum_full; /* VACUUM FULL (we have exclusive lock) */
|
bool vacuum_full; /* VACUUM FULL (we have exclusive lock) */
|
||||||
bool analyze_only; /* ANALYZE (without any actual vacuum) */
|
bool analyze_only; /* ANALYZE (without any actual vacuum) */
|
||||||
|
bool estimated_count; /* num_heap_tuples is an estimate */
|
||||||
int message_level; /* ereport level for progress messages */
|
int message_level; /* ereport level for progress messages */
|
||||||
double num_heap_tuples; /* tuples remaining in heap */
|
double num_heap_tuples; /* tuples remaining in heap */
|
||||||
BufferAccessStrategy strategy; /* access strategy for reads */
|
BufferAccessStrategy strategy; /* access strategy for reads */
|
||||||
@ -60,12 +63,15 @@ typedef struct IndexVacuumInfo
|
|||||||
*
|
*
|
||||||
* Note: pages_removed is the amount by which the index physically shrank,
|
* Note: pages_removed is the amount by which the index physically shrank,
|
||||||
* if any (ie the change in its total size on disk). pages_deleted and
|
* if any (ie the change in its total size on disk). pages_deleted and
|
||||||
* pages_free refer to free space within the index file.
|
* pages_free refer to free space within the index file. Some index AMs
|
||||||
|
* may compute num_index_tuples by reference to num_heap_tuples, in which
|
||||||
|
* case they should copy the estimated_count field from IndexVacuumInfo.
|
||||||
*/
|
*/
|
||||||
typedef struct IndexBulkDeleteResult
|
typedef struct IndexBulkDeleteResult
|
||||||
{
|
{
|
||||||
BlockNumber num_pages; /* pages remaining in index */
|
BlockNumber num_pages; /* pages remaining in index */
|
||||||
BlockNumber pages_removed; /* # removed during vacuum operation */
|
BlockNumber pages_removed; /* # removed during vacuum operation */
|
||||||
|
bool estimated_count; /* num_index_tuples is an estimate */
|
||||||
double num_index_tuples; /* tuples remaining */
|
double num_index_tuples; /* tuples remaining */
|
||||||
double tuples_removed; /* # removed during vacuum operation */
|
double tuples_removed; /* # removed during vacuum operation */
|
||||||
BlockNumber pages_deleted; /* # unused pages in index */
|
BlockNumber pages_deleted; /* # unused pages in index */
|
||||||
|
Loading…
Reference in New Issue
Block a user