aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorPeter Geoghegan <pg@bowt.ie>2023-03-23 11:16:17 -0700
committerPeter Geoghegan <pg@bowt.ie>2023-03-23 11:16:17 -0700
commitae4fdde1352fa6b2c9123e91435efafc78c370a0 (patch)
tree2f0bc32e55b16114a24d14180231a117be526e8b /src/backend
parent3b50275b12950280fb07193e24a4f400ed8a9fef (diff)
downloadpostgresql-ae4fdde1352fa6b2c9123e91435efafc78c370a0.tar.gz
postgresql-ae4fdde1352fa6b2c9123e91435efafc78c370a0.zip
Count updates that move row to a new page.
Add pgstat counter to track row updates that result in the successor version going to a new heap page, leaving behind an original version whose t_ctid points to the new version. The current count is shown by the n_tup_newpage_upd column of each of the pg_stat_*_tables views. The new n_tup_newpage_upd column complements the existing n_tup_hot_upd and n_tup_upd columns. Tables that have high n_tup_newpage_upd values (relative to n_tup_upd) are good candidates for tuning heap fillfactor. Corey Huinker, with small tweaks by me. Author: Corey Huinker <corey.huinker@gmail.com> Reviewed-By: Peter Geoghegan <pg@bowt.ie> Reviewed-By: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/CADkLM=ded21M9iZ36hHm-vj2rE2d=zcKpUQMds__Xm2pxLfHKA@mail.gmail.com
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/heap/heapam.c2
-rw-r--r--src/backend/catalog/system_views.sql4
-rw-r--r--src/backend/utils/activity/pgstat_relation.c12
-rw-r--r--src/backend/utils/adt/pgstatfuncs.c18
4 files changed, 32 insertions, 4 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index cf4b917eb4b..8abc101c8cb 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -3803,7 +3803,7 @@ l2:
if (have_tuple_lock)
UnlockTupleTuplock(relation, &(oldtup.t_self), *lockmode);
- pgstat_count_heap_update(relation, use_hot_update);
+ pgstat_count_heap_update(relation, use_hot_update, newbuf != buffer);
/*
* If heaptup is a private copy, release it. Don't forget to copy t_self
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 34ca0e739f5..8ea159dbded 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -665,6 +665,7 @@ CREATE VIEW pg_stat_all_tables AS
pg_stat_get_tuples_updated(C.oid) AS n_tup_upd,
pg_stat_get_tuples_deleted(C.oid) AS n_tup_del,
pg_stat_get_tuples_hot_updated(C.oid) AS n_tup_hot_upd,
+ pg_stat_get_tuples_newpage_updated(C.oid) AS n_tup_newpage_upd,
pg_stat_get_live_tuples(C.oid) AS n_live_tup,
pg_stat_get_dead_tuples(C.oid) AS n_dead_tup,
pg_stat_get_mod_since_analyze(C.oid) AS n_mod_since_analyze,
@@ -696,7 +697,8 @@ CREATE VIEW pg_stat_xact_all_tables AS
pg_stat_get_xact_tuples_inserted(C.oid) AS n_tup_ins,
pg_stat_get_xact_tuples_updated(C.oid) AS n_tup_upd,
pg_stat_get_xact_tuples_deleted(C.oid) AS n_tup_del,
- pg_stat_get_xact_tuples_hot_updated(C.oid) AS n_tup_hot_upd
+ pg_stat_get_xact_tuples_hot_updated(C.oid) AS n_tup_hot_upd,
+ pg_stat_get_xact_tuples_newpage_updated(C.oid) AS n_tup_newpage_upd
FROM pg_class C LEFT JOIN
pg_index I ON C.oid = I.indrelid
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index f793ac15165..b576433797a 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -373,8 +373,10 @@ pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
* count a tuple update
*/
void
-pgstat_count_heap_update(Relation rel, bool hot)
+pgstat_count_heap_update(Relation rel, bool hot, bool newpage)
{
+ Assert(!(hot && newpage));
+
if (pgstat_should_count_relation(rel))
{
PgStat_TableStatus *pgstat_info = rel->pgstat_info;
@@ -382,9 +384,14 @@ pgstat_count_heap_update(Relation rel, bool hot)
ensure_tabstat_xact_level(pgstat_info);
pgstat_info->trans->tuples_updated++;
- /* t_tuples_hot_updated is nontransactional, so just advance it */
+ /*
+ * t_tuples_hot_updated and t_tuples_newpage_updated counters are
+ * nontransactional, so just advance them
+ */
if (hot)
pgstat_info->t_counts.t_tuples_hot_updated++;
+ else if (newpage)
+ pgstat_info->t_counts.t_tuples_newpage_updated++;
}
}
@@ -804,6 +811,7 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
tabentry->tuples_updated += lstats->t_counts.t_tuples_updated;
tabentry->tuples_deleted += lstats->t_counts.t_tuples_deleted;
tabentry->tuples_hot_updated += lstats->t_counts.t_tuples_hot_updated;
+ tabentry->tuples_newpage_updated += lstats->t_counts.t_tuples_newpage_updated;
/*
* If table was truncated/dropped, first reset the live/dead counters.
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 35c6d465553..56119737c89 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -92,6 +92,9 @@ PG_STAT_GET_RELENTRY_INT64(tuples_fetched)
/* pg_stat_get_tuples_hot_updated */
PG_STAT_GET_RELENTRY_INT64(tuples_hot_updated)
+/* pg_stat_get_tuples_newpage_updated */
+PG_STAT_GET_RELENTRY_INT64(tuples_newpage_updated)
+
/* pg_stat_get_tuples_inserted */
PG_STAT_GET_RELENTRY_INT64(tuples_inserted)
@@ -1619,6 +1622,21 @@ pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS)
}
Datum
+pg_stat_get_xact_tuples_newpage_updated(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ int64 result;
+ PgStat_TableStatus *tabentry;
+
+ if ((tabentry = find_tabstat_entry(relid)) == NULL)
+ result = 0;
+ else
+ result = (int64) (tabentry->t_counts.t_tuples_newpage_updated);
+
+ PG_RETURN_INT64(result);
+}
+
+Datum
pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS)
{
Oid relid = PG_GETARG_OID(0);