<structfield>n_tup_ins</structfield> <type>bigint</type>
</para>
<para>
- Number of rows inserted
+ Total number of rows inserted
</para></entry>
</row>
<structfield>n_tup_upd</structfield> <type>bigint</type>
</para>
<para>
- Number of rows updated (includes <link linkend="storage-hot">HOT updated rows</link>)
+ Total number of rows updated. (This includes row updates
+ counted in <structfield>n_tup_hot_upd</structfield> and
+ <structfield>n_tup_newpage_upd</structfield>, and remaining
+ non-<acronym>HOT</acronym> updates.)
</para></entry>
</row>
<structfield>n_tup_del</structfield> <type>bigint</type>
</para>
<para>
- Number of rows deleted
+ Total number of rows deleted
</para></entry>
</row>
<structfield>n_tup_hot_upd</structfield> <type>bigint</type>
</para>
<para>
- Number of rows HOT updated (i.e., with no separate index
- update required)
+ Number of rows <link linkend="storage-hot">HOT updated</link>.
+ These are updates where no successor versions are required in
+ indexes.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>n_tup_newpage_upd</structfield> <type>bigint</type>
+ </para>
+ <para>
+ Number of rows updated where the successor version goes onto a
+ <emphasis>new</emphasis> heap page, leaving behind an original
+ version with a
+ <link linkend="storage-tuple-layout"><structfield>t_ctid</structfield>
+ field</link> that points to a different heap page. These are
+ always non-<acronym>HOT</acronym> updates.
</para></entry>
</row>
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
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,
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)
* 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;
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++;
}
}
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.
/* 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)
PG_RETURN_INT64(result);
}
+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)
{
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 202303181
+#define CATALOG_VERSION_NO 202303231
#endif
proname => 'pg_stat_get_tuples_hot_updated', provolatile => 's',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_tuples_hot_updated' },
+{ oid => '8614',
+ descr => 'statistics: number of tuples updated onto a new page',
+ proname => 'pg_stat_get_tuples_newpage_updated', provolatile => 's',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_tuples_newpage_updated' },
{ oid => '2878', descr => 'statistics: number of live tuples',
proname => 'pg_stat_get_live_tuples', provolatile => 's', proparallel => 'r',
prorettype => 'int8', proargtypes => 'oid',
proname => 'pg_stat_get_xact_tuples_hot_updated', provolatile => 'v',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_xact_tuples_hot_updated' },
+{ oid => '8615',
+ descr => 'statistics: number of tuples updated onto a new page in current transaction',
+ proname => 'pg_stat_get_xact_tuples_newpage_updated', provolatile => 'v',
+ proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_xact_tuples_newpage_updated' },
{ oid => '3044',
descr => 'statistics: number of blocks fetched in current transaction',
proname => 'pg_stat_get_xact_blocks_fetched', provolatile => 'v',
* the index AM, while tuples_fetched is the number of tuples successfully
* fetched by heap_fetch under the control of simple indexscans for this index.
*
- * tuples_inserted/updated/deleted/hot_updated count attempted actions,
- * regardless of whether the transaction committed. delta_live_tuples,
+ * tuples_inserted/updated/deleted/hot_updated/newpage_updated count attempted
+ * actions, regardless of whether the transaction committed. delta_live_tuples,
* delta_dead_tuples, and changed_tuples are set depending on commit or abort.
* Note that delta_live_tuples and delta_dead_tuples can be negative!
* ----------
PgStat_Counter t_tuples_updated;
PgStat_Counter t_tuples_deleted;
PgStat_Counter t_tuples_hot_updated;
+ PgStat_Counter t_tuples_newpage_updated;
bool t_truncdropped;
PgStat_Counter t_delta_live_tuples;
PgStat_Counter tuples_updated;
PgStat_Counter tuples_deleted;
PgStat_Counter tuples_hot_updated;
+ PgStat_Counter tuples_newpage_updated;
PgStat_Counter live_tuples;
PgStat_Counter dead_tuples;
} while (0)
extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n);
-extern void pgstat_count_heap_update(Relation rel, bool hot);
+extern void pgstat_count_heap_update(Relation rel, bool hot, bool newpage);
extern void pgstat_count_heap_delete(Relation rel);
extern void pgstat_count_truncate(Relation rel);
extern void pgstat_update_heap_dead_tuples(Relation rel, int delta);
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,
n_tup_upd,
n_tup_del,
n_tup_hot_upd,
+ n_tup_newpage_upd,
n_live_tup,
n_dead_tup,
n_mod_since_analyze,
n_tup_upd,
n_tup_del,
n_tup_hot_upd,
+ n_tup_newpage_upd,
n_live_tup,
n_dead_tup,
n_mod_since_analyze,
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)))
n_tup_ins,
n_tup_upd,
n_tup_del,
- n_tup_hot_upd
+ n_tup_hot_upd,
+ n_tup_newpage_upd
FROM pg_stat_xact_all_tables
WHERE ((schemaname = ANY (ARRAY['pg_catalog'::name, 'information_schema'::name])) OR (schemaname ~ '^pg_toast'::text));
pg_stat_xact_user_functions| SELECT p.oid AS funcid,
n_tup_ins,
n_tup_upd,
n_tup_del,
- n_tup_hot_upd
+ n_tup_hot_upd,
+ n_tup_newpage_upd
FROM pg_stat_xact_all_tables
WHERE ((schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (schemaname !~ '^pg_toast'::text));
pg_statio_all_indexes| SELECT c.oid AS relid,