1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-21 00:42:43 +03:00

Add relallfrozen to pg_class

Add relallfrozen, an estimate of the number of pages marked all-frozen
in the visibility map.

pg_class already has relallvisible, an estimate of the number of pages
in the relation marked all-visible in the visibility map. This is used
primarily for planning.

relallfrozen, together with relallvisible, is useful for estimating the
outstanding number of all-visible but not all-frozen pages in the
relation for the purposes of scheduling manual VACUUMs and tuning vacuum
freeze parameters.

A future commit will use relallfrozen to trigger more frequent vacuums
on insert-focused workloads with significant volume of frozen data.

Bump catalog version

Author: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>
Reviewed-by: Robert Treat <rob@xzilla.net>
Reviewed-by: Corey Huinker <corey.huinker@gmail.com>
Reviewed-by: Greg Sabino Mullane <htamfids@gmail.com>
Discussion: https://postgr.es/m/flat/CAAKRu_aj-P7YyBz_cPNwztz6ohP%2BvWis%3Diz3YcomkB3NpYA--w%40mail.gmail.com
This commit is contained in:
Melanie Plageman
2025-03-03 11:18:05 -05:00
parent 8492feb98f
commit 99f8f3fbbc
14 changed files with 190 additions and 70 deletions

View File

@@ -623,7 +623,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
minmulti_updated;
BlockNumber orig_rel_pages,
new_rel_pages,
new_rel_allvisible;
new_rel_allvisible,
new_rel_allfrozen;
PGRUsage ru0;
TimestampTz starttime = 0;
PgStat_Counter startreadtime = 0,
@@ -898,10 +899,18 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
* pg_class.relpages to
*/
new_rel_pages = vacrel->rel_pages; /* After possible rel truncation */
visibilitymap_count(rel, &new_rel_allvisible, NULL);
visibilitymap_count(rel, &new_rel_allvisible, &new_rel_allfrozen);
if (new_rel_allvisible > new_rel_pages)
new_rel_allvisible = new_rel_pages;
/*
* An all-frozen block _must_ be all-visible. As such, clamp the count of
* all-frozen blocks to the count of all-visible blocks. This matches the
* clamping of relallvisible above.
*/
if (new_rel_allfrozen > new_rel_allvisible)
new_rel_allfrozen = new_rel_allvisible;
/*
* Now actually update rel's pg_class entry.
*
@@ -910,7 +919,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params,
* scan every page that isn't skipped using the visibility map.
*/
vac_update_relstats(rel, new_rel_pages, vacrel->new_live_tuples,
new_rel_allvisible, vacrel->nindexes > 0,
new_rel_allvisible, new_rel_allfrozen,
vacrel->nindexes > 0,
vacrel->NewRelfrozenXid, vacrel->NewRelminMxid,
&frozenxid_updated, &minmulti_updated, false);
@@ -3720,7 +3730,7 @@ update_relstats_all_indexes(LVRelState *vacrel)
vac_update_relstats(indrel,
istat->num_pages,
istat->num_index_tuples,
0,
0, 0,
false,
InvalidTransactionId,
InvalidMultiXactId,

View File

@@ -924,6 +924,7 @@ InsertPgClassTuple(Relation pg_class_desc,
values[Anum_pg_class_relpages - 1] = Int32GetDatum(rd_rel->relpages);
values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
values[Anum_pg_class_relallfrozen - 1] = Int32GetDatum(rd_rel->relallfrozen);
values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
@@ -994,6 +995,7 @@ AddNewRelationTuple(Relation pg_class_desc,
new_rel_reltup->relpages = 0;
new_rel_reltup->reltuples = -1;
new_rel_reltup->relallvisible = 0;
new_rel_reltup->relallfrozen = 0;
/* Sequences always have a known size */
if (relkind == RELKIND_SEQUENCE)

View File

@@ -2793,8 +2793,8 @@ FormIndexDatum(IndexInfo *indexInfo,
* hasindex: set relhasindex to this value
* reltuples: if >= 0, set reltuples to this value; else no change
*
* If reltuples >= 0, relpages and relallvisible are also updated (using
* RelationGetNumberOfBlocks() and visibilitymap_count()).
* If reltuples >= 0, relpages, relallvisible, and relallfrozen are also
* updated (using RelationGetNumberOfBlocks() and visibilitymap_count()).
*
* NOTE: an important side-effect of this operation is that an SI invalidation
* message is sent out to all backends --- including me --- causing relcache
@@ -2812,6 +2812,7 @@ index_update_stats(Relation rel,
bool update_stats;
BlockNumber relpages = 0; /* keep compiler quiet */
BlockNumber relallvisible = 0;
BlockNumber relallfrozen = 0;
Oid relid = RelationGetRelid(rel);
Relation pg_class;
ScanKeyData key[1];
@@ -2851,7 +2852,7 @@ index_update_stats(Relation rel,
relpages = RelationGetNumberOfBlocks(rel);
if (rel->rd_rel->relkind != RELKIND_INDEX)
visibilitymap_count(rel, &relallvisible, NULL);
visibilitymap_count(rel, &relallvisible, &relallfrozen);
}
/*
@@ -2924,6 +2925,11 @@ index_update_stats(Relation rel,
rd_rel->relallvisible = (int32) relallvisible;
dirty = true;
}
if (rd_rel->relallfrozen != (int32) relallfrozen)
{
rd_rel->relallfrozen = (int32) relallfrozen;
dirty = true;
}
}
/*

View File

@@ -630,12 +630,11 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
*/
if (!inh)
{
BlockNumber relallvisible;
BlockNumber relallvisible = 0;
BlockNumber relallfrozen = 0;
if (RELKIND_HAS_STORAGE(onerel->rd_rel->relkind))
visibilitymap_count(onerel, &relallvisible, NULL);
else
relallvisible = 0;
visibilitymap_count(onerel, &relallvisible, &relallfrozen);
/*
* Update pg_class for table relation. CCI first, in case acquirefunc
@@ -646,6 +645,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
relpages,
totalrows,
relallvisible,
relallfrozen,
hasindex,
InvalidTransactionId,
InvalidMultiXactId,
@@ -662,7 +662,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
vac_update_relstats(Irel[ind],
RelationGetNumberOfBlocks(Irel[ind]),
totalindexrows,
0,
0, 0,
false,
InvalidTransactionId,
InvalidMultiXactId,
@@ -678,7 +678,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
*/
CommandCounterIncrement();
vac_update_relstats(onerel, -1, totalrows,
0, hasindex, InvalidTransactionId,
0, 0, hasindex, InvalidTransactionId,
InvalidMultiXactId,
NULL, NULL,
in_outer_xact);

View File

@@ -1226,6 +1226,7 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
int32 swap_pages;
float4 swap_tuples;
int32 swap_allvisible;
int32 swap_allfrozen;
swap_pages = relform1->relpages;
relform1->relpages = relform2->relpages;
@@ -1238,6 +1239,10 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
swap_allvisible = relform1->relallvisible;
relform1->relallvisible = relform2->relallvisible;
relform2->relallvisible = swap_allvisible;
swap_allfrozen = relform1->relallfrozen;
relform1->relallfrozen = relform2->relallfrozen;
relform2->relallfrozen = swap_allfrozen;
}
/*

View File

@@ -1427,6 +1427,7 @@ void
vac_update_relstats(Relation relation,
BlockNumber num_pages, double num_tuples,
BlockNumber num_all_visible_pages,
BlockNumber num_all_frozen_pages,
bool hasindex, TransactionId frozenxid,
MultiXactId minmulti,
bool *frozenxid_updated, bool *minmulti_updated,
@@ -1476,6 +1477,11 @@ vac_update_relstats(Relation relation,
pgcform->relallvisible = (int32) num_all_visible_pages;
dirty = true;
}
if (pgcform->relallfrozen != (int32) num_all_frozen_pages)
{
pgcform->relallfrozen = (int32) num_all_frozen_pages;
dirty = true;
}
/* Apply DDL updates, but not inside an outer transaction (see above) */

View File

@@ -36,6 +36,7 @@ enum relation_stats_argnum
RELPAGES_ARG,
RELTUPLES_ARG,
RELALLVISIBLE_ARG,
RELALLFROZEN_ARG,
NUM_RELATION_STATS_ARGS
};
@@ -45,6 +46,7 @@ static struct StatsArgInfo relarginfo[] =
[RELPAGES_ARG] = {"relpages", INT4OID},
[RELTUPLES_ARG] = {"reltuples", FLOAT4OID},
[RELALLVISIBLE_ARG] = {"relallvisible", INT4OID},
[RELALLFROZEN_ARG] = {"relallfrozen", INT4OID},
[NUM_RELATION_STATS_ARGS] = {0}
};
@@ -65,11 +67,13 @@ relation_statistics_update(FunctionCallInfo fcinfo)
bool update_reltuples = false;
BlockNumber relallvisible = 0;
bool update_relallvisible = false;
BlockNumber relallfrozen = 0;
bool update_relallfrozen = false;
HeapTuple ctup;
Form_pg_class pgcform;
int replaces[3] = {0};
Datum values[3] = {0};
bool nulls[3] = {0};
int replaces[4] = {0};
Datum values[4] = {0};
bool nulls[4] = {0};
int nreplaces = 0;
if (!PG_ARGISNULL(RELPAGES_ARG))
@@ -98,6 +102,12 @@ relation_statistics_update(FunctionCallInfo fcinfo)
update_relallvisible = true;
}
if (!PG_ARGISNULL(RELALLFROZEN_ARG))
{
relallfrozen = PG_GETARG_UINT32(RELALLFROZEN_ARG);
update_relallfrozen = true;
}
stats_check_required_arg(fcinfo, relarginfo, RELATION_ARG);
reloid = PG_GETARG_OID(RELATION_ARG);
@@ -148,6 +158,13 @@ relation_statistics_update(FunctionCallInfo fcinfo)
nreplaces++;
}
if (update_relallfrozen && relallfrozen != pgcform->relallfrozen)
{
replaces[nreplaces] = Anum_pg_class_relallfrozen;
values[nreplaces] = UInt32GetDatum(relallfrozen);
nreplaces++;
}
if (nreplaces > 0)
{
TupleDesc tupdesc = RelationGetDescr(crel);
@@ -176,9 +193,9 @@ relation_statistics_update(FunctionCallInfo fcinfo)
Datum
pg_clear_relation_stats(PG_FUNCTION_ARGS)
{
LOCAL_FCINFO(newfcinfo, 4);
LOCAL_FCINFO(newfcinfo, 5);
InitFunctionCallInfoData(*newfcinfo, NULL, 4, InvalidOid, NULL, NULL);
InitFunctionCallInfoData(*newfcinfo, NULL, 5, InvalidOid, NULL, NULL);
newfcinfo->args[0].value = PG_GETARG_OID(0);
newfcinfo->args[0].isnull = PG_ARGISNULL(0);
@@ -188,6 +205,8 @@ pg_clear_relation_stats(PG_FUNCTION_ARGS)
newfcinfo->args[2].isnull = false;
newfcinfo->args[3].value = UInt32GetDatum(0);
newfcinfo->args[3].isnull = false;
newfcinfo->args[4].value = UInt32GetDatum(0);
newfcinfo->args[4].isnull = false;
relation_statistics_update(newfcinfo);
PG_RETURN_VOID();

View File

@@ -1928,6 +1928,7 @@ formrdesc(const char *relationName, Oid relationReltype,
relation->rd_rel->relpages = 0;
relation->rd_rel->reltuples = -1;
relation->rd_rel->relallvisible = 0;
relation->rd_rel->relallfrozen = 0;
relation->rd_rel->relkind = RELKIND_RELATION;
relation->rd_rel->relnatts = (int16) natts;
@@ -3885,6 +3886,7 @@ RelationSetNewRelfilenumber(Relation relation, char persistence)
classform->relpages = 0; /* it's empty until further notice */
classform->reltuples = -1;
classform->relallvisible = 0;
classform->relallfrozen = 0;
}
classform->relfrozenxid = freezeXid;
classform->relminmxid = minmulti;