public inbox for [email protected]
help / color / mirror / Atom feedFrom: Bertrand Drouvot <[email protected]>
Subject: [PATCH v1] Provide relfilenode statistics
Date: Thu, 16 Nov 2023 02:30:01 +0000
---
src/backend/access/rmgrdesc/xactdesc.c | 5 +-
src/backend/catalog/storage.c | 8 ++
src/backend/catalog/system_functions.sql | 2 +-
src/backend/catalog/system_views.sql | 5 +-
src/backend/postmaster/checkpointer.c | 5 +
src/backend/storage/buffer/bufmgr.c | 6 +-
src/backend/storage/smgr/md.c | 7 ++
src/backend/utils/activity/pgstat.c | 39 ++++--
src/backend/utils/activity/pgstat_database.c | 12 +-
src/backend/utils/activity/pgstat_function.c | 13 +-
src/backend/utils/activity/pgstat_relation.c | 112 ++++++++++++++++--
src/backend/utils/activity/pgstat_replslot.c | 13 +-
src/backend/utils/activity/pgstat_shmem.c | 19 ++-
.../utils/activity/pgstat_subscription.c | 12 +-
src/backend/utils/activity/pgstat_xact.c | 60 +++++++---
src/backend/utils/adt/pgstatfuncs.c | 34 +++++-
src/include/access/tableam.h | 19 +++
src/include/access/xact.h | 1 +
src/include/catalog/pg_proc.dat | 14 ++-
src/include/pgstat.h | 19 ++-
src/include/utils/pgstat_internal.h | 34 ++++--
src/test/recovery/t/029_stats_restart.pl | 40 +++----
.../recovery/t/030_stats_cleanup_replica.pl | 6 +-
src/test/regress/expected/rules.out | 12 +-
src/test/regress/expected/stats.out | 30 ++---
src/test/regress/sql/stats.sql | 30 ++---
src/test/subscription/t/026_stats.pl | 4 +-
src/tools/pgindent/typedefs.list | 1 +
28 files changed, 415 insertions(+), 147 deletions(-)
4.6% src/backend/catalog/
47.8% src/backend/utils/activity/
6.5% src/backend/utils/adt/
3.7% src/backend/
3.3% src/include/access/
3.3% src/include/catalog/
6.2% src/include/utils/
3.3% src/include/
12.1% src/test/recovery/t/
5.5% src/test/regress/expected/
3.0% src/test/
diff --git a/src/backend/access/rmgrdesc/xactdesc.c b/src/backend/access/rmgrdesc/xactdesc.c
index dccca201e0..c02b079645 100644
--- a/src/backend/access/rmgrdesc/xactdesc.c
+++ b/src/backend/access/rmgrdesc/xactdesc.c
@@ -319,10 +319,11 @@ xact_desc_stats(StringInfo buf, const char *label,
appendStringInfo(buf, "; %sdropped stats:", label);
for (i = 0; i < ndropped; i++)
{
- appendStringInfo(buf, " %d/%u/%u",
+ appendStringInfo(buf, " %d/%u/%u/%u",
dropped_stats[i].kind,
dropped_stats[i].dboid,
- dropped_stats[i].objoid);
+ dropped_stats[i].objoid,
+ dropped_stats[i].relfile);
}
}
}
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index f56b3cc0f2..db6107cd90 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -33,6 +33,7 @@
#include "storage/smgr.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
+#include "utils/pgstat_internal.h"
#include "utils/rel.h"
/* GUC variables */
@@ -152,6 +153,7 @@ RelationCreateStorage(RelFileLocator rlocator, char relpersistence,
if (needs_wal)
log_smgrcreate(&srel->smgr_rlocator.locator, MAIN_FORKNUM);
+ pgstat_create_transactional(PGSTAT_KIND_RELFILENODE, rlocator.dbOid, rlocator.spcOid, rlocator.relNumber);
/*
* Add the relation to the list of stuff to delete at abort, if we are
* asked to do so.
@@ -227,6 +229,8 @@ RelationDropStorage(Relation rel)
* for now I'll keep the logic simple.
*/
+ pgstat_drop_transactional(PGSTAT_KIND_RELFILENODE, rel->rd_locator.dbOid, rel->rd_locator.spcOid, rel->rd_locator.relNumber);
+
RelationCloseSmgr(rel);
}
@@ -253,6 +257,9 @@ RelationPreserveStorage(RelFileLocator rlocator, bool atCommit)
PendingRelDelete *pending;
PendingRelDelete *prev;
PendingRelDelete *next;
+ PgStat_SubXactStatus *xact_state;
+
+ xact_state = pgStatXactStack;
prev = NULL;
for (pending = pendingDeletes; pending != NULL; pending = next)
@@ -267,6 +274,7 @@ RelationPreserveStorage(RelFileLocator rlocator, bool atCommit)
else
pendingDeletes = next;
pfree(pending);
+ PgStat_RemoveRelFileNodeFromDroppedStats(xact_state, rlocator);
/* prev does not change */
}
else
diff --git a/src/backend/catalog/system_functions.sql b/src/backend/catalog/system_functions.sql
index ae099e328c..140c8d556c 100644
--- a/src/backend/catalog/system_functions.sql
+++ b/src/backend/catalog/system_functions.sql
@@ -681,7 +681,7 @@ REVOKE EXECUTE ON FUNCTION pg_stat_reset_single_function_counters(oid) FROM publ
REVOKE EXECUTE ON FUNCTION pg_stat_reset_replication_slot(text) FROM public;
-REVOKE EXECUTE ON FUNCTION pg_stat_have_stats(text, oid, oid) FROM public;
+REVOKE EXECUTE ON FUNCTION pg_stat_have_stats(text, oid, oid, oid) FROM public;
REVOKE EXECUTE ON FUNCTION pg_stat_reset_subscription_stats(oid) FROM public;
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 53047cab5f..b0d7af6df0 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -750,6 +750,7 @@ CREATE VIEW pg_statio_all_tables AS
C.relname AS relname,
pg_stat_get_blocks_fetched(C.oid) -
pg_stat_get_blocks_hit(C.oid) AS heap_blks_read,
+ pg_stat_get_blocks_written(C.oid) + pg_stat_get_relfilenode_blocks_written(d.oid, CASE WHEN C.reltablespace <> 0 THEN C.reltablespace ELSE d.dattablespace END, C.relfilenode) AS heap_blks_written,
pg_stat_get_blocks_hit(C.oid) AS heap_blks_hit,
I.idx_blks_read AS idx_blks_read,
I.idx_blks_hit AS idx_blks_hit,
@@ -758,7 +759,7 @@ CREATE VIEW pg_statio_all_tables AS
pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit,
X.idx_blks_read AS tidx_blks_read,
X.idx_blks_hit AS tidx_blks_hit
- FROM pg_class C LEFT JOIN
+ FROM pg_database d, pg_class C LEFT JOIN
pg_class T ON C.reltoastrelid = T.oid
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
LEFT JOIN LATERAL (
@@ -775,7 +776,7 @@ CREATE VIEW pg_statio_all_tables AS
sum(pg_stat_get_blocks_hit(indexrelid))::bigint
AS idx_blks_hit
FROM pg_index WHERE indrelid = T.oid ) X ON true
- WHERE C.relkind IN ('r', 't', 'm');
+ WHERE C.relkind IN ('r', 't', 'm') AND d.datname = current_database();
CREATE VIEW pg_statio_sys_tables AS
SELECT * FROM pg_statio_all_tables
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index 3c68a9904d..0ff2812218 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -519,6 +519,11 @@ CheckpointerMain(char *startup_data, size_t startup_data_len)
/* Report pending statistics to the cumulative stats system */
pgstat_report_checkpointer();
pgstat_report_wal(true);
+ /*
+ * No need to check for transaction state in checkpointer before
+ * calling pgstat_report_stat().
+ */
+ pgstat_report_stat(true);
/*
* If any checkpoint flags have been set, redo the loop to handle the
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 49637284f9..06d89ba26b 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -1121,9 +1121,9 @@ PinBufferForBlock(Relation rel,
* WaitReadBuffers() (so, not for hits, and not for buffers that are
* zeroed instead), the per-relation stats always count them.
*/
- pgstat_count_buffer_read(rel);
+ pgstat_report_relfilenode_buffer_read(rel);
if (*foundPtr)
- pgstat_count_buffer_hit(rel);
+ pgstat_report_relfilenode_buffer_hit(rel);
}
if (*foundPtr)
{
@@ -3838,6 +3838,8 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln, IOObject io_object,
pgBufferUsage.shared_blks_written++;
+ pgstat_report_relfilenode_blks_written(reln->smgr_rlocator.locator);
+
/*
* Mark the buffer as clean (unless BM_JUST_DIRTIED has become set) and
* end the BM_IO_IN_PROGRESS state.
diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index bf0f3ca76d..3576749d2d 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -1447,12 +1447,16 @@ DropRelationFiles(RelFileLocator *delrels, int ndelrels, bool isRedo)
{
SMgrRelation *srels;
int i;
+ int not_freed_count = 0;
srels = palloc(sizeof(SMgrRelation) * ndelrels);
for (i = 0; i < ndelrels; i++)
{
SMgrRelation srel = smgropen(delrels[i], INVALID_PROC_NUMBER);
+ if (!pgstat_drop_entry(PGSTAT_KIND_RELFILENODE, delrels[i].dbOid, delrels[i].spcOid, delrels[i].relNumber))
+ not_freed_count++;
+
if (isRedo)
{
ForkNumber fork;
@@ -1463,6 +1467,9 @@ DropRelationFiles(RelFileLocator *delrels, int ndelrels, bool isRedo)
srels[i] = srel;
}
+ if (not_freed_count > 0)
+ pgstat_request_entry_refs_gc();
+
smgrdounlinkall(srels, ndelrels, isRedo);
for (i = 0; i < ndelrels; i++)
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index dcc2ad8d95..e3b6f45828 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -288,6 +288,19 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = {
.delete_pending_cb = pgstat_relation_delete_pending_cb,
},
+ [PGSTAT_KIND_RELFILENODE] = {
+ .name = "relfilenode",
+
+ .fixed_amount = false,
+
+ .shared_size = sizeof(PgStatShared_RelFileNode),
+ .shared_data_off = offsetof(PgStatShared_RelFileNode, stats),
+ .shared_data_len = sizeof(((PgStatShared_RelFileNode *) 0)->stats),
+ .pending_size = sizeof(PgStat_StatRelFileNodeEntry),
+
+ .flush_pending_cb = pgstat_relfilenode_flush_cb,
+ },
+
[PGSTAT_KIND_FUNCTION] = {
.name = "function",
@@ -651,7 +664,7 @@ pgstat_report_stat(bool force)
partial_flush = false;
- /* flush database / relation / function / ... stats */
+ /* flush database / relation / function / relfilenode / ... stats */
partial_flush |= pgstat_flush_pending_entries(nowait);
/* flush IO stats */
@@ -731,7 +744,7 @@ pgstat_reset_counters(void)
* GRANT system.
*/
void
-pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid)
+pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile)
{
const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
TimestampTz ts = GetCurrentTimestamp();
@@ -740,7 +753,7 @@ pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid)
Assert(!pgstat_get_kind_info(kind)->fixed_amount);
/* reset the "single counter" */
- pgstat_reset_entry(kind, dboid, objoid, ts);
+ pgstat_reset_entry(kind, dboid, objoid, relfile, ts);
if (!kind_info->accessed_across_databases)
pgstat_reset_database_timestamp(dboid, ts);
@@ -809,7 +822,7 @@ pgstat_clear_snapshot(void)
}
void *
-pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
+pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile)
{
PgStat_HashKey key;
PgStat_EntryRef *entry_ref;
@@ -825,6 +838,7 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
key.kind = kind;
key.dboid = dboid;
key.objoid = objoid;
+ key.relfile = relfile;
/* if we need to build a full snapshot, do so */
if (pgstat_fetch_consistency == PGSTAT_FETCH_CONSISTENCY_SNAPSHOT)
@@ -850,7 +864,7 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
pgStatLocal.snapshot.mode = pgstat_fetch_consistency;
- entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL);
+ entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, relfile, false, NULL);
if (entry_ref == NULL || entry_ref->shared_entry->dropped)
{
@@ -919,13 +933,13 @@ pgstat_get_stat_snapshot_timestamp(bool *have_snapshot)
}
bool
-pgstat_have_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
+pgstat_have_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile)
{
/* fixed-numbered stats always exist */
if (pgstat_get_kind_info(kind)->fixed_amount)
return true;
- return pgstat_get_entry_ref(kind, dboid, objoid, false, NULL) != NULL;
+ return pgstat_get_entry_ref(kind, dboid, objoid, relfile, false, NULL) != NULL;
}
/*
@@ -1102,7 +1116,8 @@ pgstat_build_snapshot_fixed(PgStat_Kind kind)
* created, false otherwise.
*/
PgStat_EntryRef *
-pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry)
+pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid,
+ RelFileNumber relfile, bool *created_entry)
{
PgStat_EntryRef *entry_ref;
@@ -1117,7 +1132,7 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created
ALLOCSET_SMALL_SIZES);
}
- entry_ref = pgstat_get_entry_ref(kind, dboid, objoid,
+ entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, relfile,
true, created_entry);
if (entry_ref->pending == NULL)
@@ -1140,11 +1155,11 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created
* that it shouldn't be needed.
*/
PgStat_EntryRef *
-pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
+pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile)
{
PgStat_EntryRef *entry_ref;
- entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL);
+ entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, relfile, false, NULL);
if (entry_ref == NULL || entry_ref->pending == NULL)
return NULL;
@@ -1173,7 +1188,7 @@ pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref)
}
/*
- * Flush out pending stats for database objects (databases, relations,
+ * Flush out pending stats for database objects (databases, relations, relfilenodes,
* functions).
*/
static bool
diff --git a/src/backend/utils/activity/pgstat_database.c b/src/backend/utils/activity/pgstat_database.c
index 29bc090974..cf77f2dbdb 100644
--- a/src/backend/utils/activity/pgstat_database.c
+++ b/src/backend/utils/activity/pgstat_database.c
@@ -43,7 +43,7 @@ static PgStat_Counter pgLastSessionReportTime = 0;
void
pgstat_drop_database(Oid databaseid)
{
- pgstat_drop_transactional(PGSTAT_KIND_DATABASE, databaseid, InvalidOid);
+ pgstat_drop_transactional(PGSTAT_KIND_DATABASE, databaseid, InvalidOid, InvalidOid);
}
/*
@@ -66,7 +66,7 @@ pgstat_report_autovac(Oid dboid)
* operation so it doesn't matter if we get blocked here a little.
*/
entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE,
- dboid, InvalidOid, false);
+ dboid, InvalidOid, InvalidOid, false);
dbentry = (PgStatShared_Database *) entry_ref->shared_stats;
dbentry->stats.last_autovac_time = GetCurrentTimestamp();
@@ -150,7 +150,7 @@ pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
* common enough for that to be a problem.
*/
entry_ref =
- pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, dboid, InvalidOid, false);
+ pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, dboid, InvalidOid, InvalidOid, false);
sharedent = (PgStatShared_Database *) entry_ref->shared_stats;
sharedent->stats.checksum_failures += failurecount;
@@ -242,7 +242,7 @@ PgStat_StatDBEntry *
pgstat_fetch_stat_dbentry(Oid dboid)
{
return (PgStat_StatDBEntry *)
- pgstat_fetch_entry(PGSTAT_KIND_DATABASE, dboid, InvalidOid);
+ pgstat_fetch_entry(PGSTAT_KIND_DATABASE, dboid, InvalidOid, InvalidOid);
}
void
@@ -341,7 +341,7 @@ pgstat_prep_database_pending(Oid dboid)
Assert(!OidIsValid(dboid) || OidIsValid(MyDatabaseId));
entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_DATABASE, dboid, InvalidOid,
- NULL);
+ InvalidOid, NULL);
return entry_ref->pending;
}
@@ -357,7 +357,7 @@ pgstat_reset_database_timestamp(Oid dboid, TimestampTz ts)
PgStatShared_Database *dbentry;
dbref = pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, MyDatabaseId, InvalidOid,
- false);
+ InvalidOid, false);
dbentry = (PgStatShared_Database *) dbref->shared_stats;
dbentry->stats.stat_reset_timestamp = ts;
diff --git a/src/backend/utils/activity/pgstat_function.c b/src/backend/utils/activity/pgstat_function.c
index d26da551a4..440e44e300 100644
--- a/src/backend/utils/activity/pgstat_function.c
+++ b/src/backend/utils/activity/pgstat_function.c
@@ -46,7 +46,8 @@ pgstat_create_function(Oid proid)
{
pgstat_create_transactional(PGSTAT_KIND_FUNCTION,
MyDatabaseId,
- proid);
+ proid,
+ InvalidOid);
}
/*
@@ -61,7 +62,8 @@ pgstat_drop_function(Oid proid)
{
pgstat_drop_transactional(PGSTAT_KIND_FUNCTION,
MyDatabaseId,
- proid);
+ proid,
+ InvalidOid);
}
/*
@@ -86,6 +88,7 @@ pgstat_init_function_usage(FunctionCallInfo fcinfo,
entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_FUNCTION,
MyDatabaseId,
fcinfo->flinfo->fn_oid,
+ InvalidOid,
&created_entry);
/*
@@ -113,7 +116,7 @@ pgstat_init_function_usage(FunctionCallInfo fcinfo,
if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(fcinfo->flinfo->fn_oid)))
{
pgstat_drop_entry(PGSTAT_KIND_FUNCTION, MyDatabaseId,
- fcinfo->flinfo->fn_oid);
+ fcinfo->flinfo->fn_oid, InvalidOid);
ereport(ERROR, errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("function call to dropped function"));
}
@@ -224,7 +227,7 @@ find_funcstat_entry(Oid func_id)
{
PgStat_EntryRef *entry_ref;
- entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_FUNCTION, MyDatabaseId, func_id);
+ entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_FUNCTION, MyDatabaseId, func_id, InvalidOid);
if (entry_ref)
return entry_ref->pending;
@@ -239,5 +242,5 @@ PgStat_StatFuncEntry *
pgstat_fetch_stat_funcentry(Oid func_id)
{
return (PgStat_StatFuncEntry *)
- pgstat_fetch_entry(PGSTAT_KIND_FUNCTION, MyDatabaseId, func_id);
+ pgstat_fetch_entry(PGSTAT_KIND_FUNCTION, MyDatabaseId, func_id, InvalidOid);
}
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index 8a3f7d434c..136dd6c85b 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -44,6 +44,7 @@ typedef struct TwoPhasePgStatRecord
static PgStat_TableStatus *pgstat_prep_relation_pending(Oid rel_id, bool isshared);
+PgStat_StatRelFileNodeEntry *pgstat_prep_relfilenode_pending(RelFileLocator locator);
static void add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level);
static void ensure_tabstat_xact_level(PgStat_TableStatus *pgstat_info);
static void save_truncdrop_counters(PgStat_TableXactStatus *trans, bool is_drop);
@@ -69,6 +70,7 @@ pgstat_copy_relation_stats(Relation dst, Relation src)
dst_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION,
dst->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
RelationGetRelid(dst),
+ InvalidOid,
false);
dstshstats = (PgStatShared_Relation *) dst_ref->shared_stats;
@@ -170,7 +172,7 @@ pgstat_create_relation(Relation rel)
{
pgstat_create_transactional(PGSTAT_KIND_RELATION,
rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
- RelationGetRelid(rel));
+ RelationGetRelid(rel), InvalidOid);
}
/*
@@ -184,7 +186,7 @@ pgstat_drop_relation(Relation rel)
pgstat_drop_transactional(PGSTAT_KIND_RELATION,
rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId,
- RelationGetRelid(rel));
+ RelationGetRelid(rel), InvalidOid);
if (!pgstat_should_count_relation(rel))
return;
@@ -225,7 +227,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
/* block acquiring lock for the same reason as pgstat_report_autovac() */
entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION,
- dboid, tableoid, false);
+ dboid, tableoid, InvalidOid, false);
shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
tabentry = &shtabentry->stats;
@@ -318,6 +320,7 @@ pgstat_report_analyze(Relation rel,
/* block acquiring lock for the same reason as pgstat_report_autovac() */
entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_RELATION, dboid,
RelationGetRelid(rel),
+ InvalidOid,
false);
/* can't get dropped while accessed */
Assert(entry_ref != NULL && entry_ref->shared_stats != NULL);
@@ -458,6 +461,19 @@ pgstat_fetch_stat_tabentry(Oid relid)
return pgstat_fetch_stat_tabentry_ext(IsSharedRelation(relid), relid);
}
+/*
+ * Support function for the SQL-callable pgstat* functions. Returns
+ * the collected statistics for one relfilenode or NULL. NULL doesn't mean
+ * that the relfilenode doesn't exist, just that there are no statistics, so the
+ * caller is better off to report ZERO instead.
+ */
+PgStat_StatRelFileNodeEntry *
+pgstat_fetch_stat_relfilenodeentry(Oid dboid, Oid spcOid, RelFileNumber relfile)
+{
+ return (PgStat_StatRelFileNodeEntry *)
+ pgstat_fetch_entry(PGSTAT_KIND_RELFILENODE, dboid, spcOid, relfile);
+}
+
/*
* More efficient version of pgstat_fetch_stat_tabentry(), allowing to specify
* whether the to-be-accessed table is a shared relation or not.
@@ -468,7 +484,7 @@ pgstat_fetch_stat_tabentry_ext(bool shared, Oid reloid)
Oid dboid = (shared ? InvalidOid : MyDatabaseId);
return (PgStat_StatTabEntry *)
- pgstat_fetch_entry(PGSTAT_KIND_RELATION, dboid, reloid);
+ pgstat_fetch_entry(PGSTAT_KIND_RELATION, dboid, reloid, InvalidOid);
}
/*
@@ -491,10 +507,10 @@ find_tabstat_entry(Oid rel_id)
PgStat_TableStatus *tabentry = NULL;
PgStat_TableStatus *tablestatus = NULL;
- entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, MyDatabaseId, rel_id);
+ entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, MyDatabaseId, rel_id, InvalidOid);
if (!entry_ref)
{
- entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, InvalidOid, rel_id);
+ entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION, InvalidOid, rel_id, InvalidOid);
if (!entry_ref)
return tablestatus;
}
@@ -881,6 +897,38 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
return true;
}
+/*
+ * Flush out pending stats for the relfilenode entry
+ *
+ * If nowait is true, this function returns false if lock could not
+ * immediately acquired, otherwise true is returned.
+ */
+bool
+pgstat_relfilenode_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
+{
+ PgStatShared_RelFileNode *sharedent;
+ PgStat_StatRelFileNodeEntry *pendingent;
+
+ pendingent = (PgStat_StatRelFileNodeEntry *) entry_ref->pending;
+ sharedent = (PgStatShared_RelFileNode *) entry_ref->shared_stats;
+
+ if (!pgstat_lock_entry(entry_ref, nowait))
+ return false;
+
+#define PGSTAT_ACCUM_RELFILENODECOUNT(item) \
+ (sharedent)->stats.item += (pendingent)->item
+
+ PGSTAT_ACCUM_RELFILENODECOUNT(blocks_fetched);
+ PGSTAT_ACCUM_RELFILENODECOUNT(blocks_hit);
+ PGSTAT_ACCUM_RELFILENODECOUNT(blocks_written);
+
+ pgstat_unlock_entry(entry_ref);
+
+ memset(pendingent, 0, sizeof(*pendingent));
+
+ return true;
+}
+
void
pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref)
{
@@ -902,7 +950,7 @@ pgstat_prep_relation_pending(Oid rel_id, bool isshared)
entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_RELATION,
isshared ? InvalidOid : MyDatabaseId,
- rel_id, NULL);
+ rel_id, InvalidOid, NULL);
pending = entry_ref->pending;
pending->id = rel_id;
pending->shared = isshared;
@@ -910,6 +958,56 @@ pgstat_prep_relation_pending(Oid rel_id, bool isshared)
return pending;
}
+PgStat_StatRelFileNodeEntry *
+pgstat_prep_relfilenode_pending(RelFileLocator locator)
+{
+ PgStat_EntryRef *entry_ref;
+
+ entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_RELFILENODE, locator.dbOid,
+ locator.spcOid, locator.relNumber, NULL);
+
+ return entry_ref->pending;
+}
+
+void
+pgstat_report_relfilenode_blks_written(RelFileLocator locator)
+{
+ PgStat_StatRelFileNodeEntry *relfileentry = NULL;
+
+ relfileentry = pgstat_prep_relfilenode_pending(locator);
+
+ if (relfileentry)
+ relfileentry->blocks_written++;
+}
+
+void
+pgstat_report_relfilenode_buffer_read(Relation reln)
+{
+ PgStat_StatRelFileNodeEntry *relfileentry = NULL;
+
+ /* For relation stats to survive after a rewrite */
+ pgstat_count_buffer_read(reln);
+
+ relfileentry = pgstat_prep_relfilenode_pending(reln->rd_locator);
+
+ if (relfileentry)
+ relfileentry->blocks_fetched++;
+}
+
+void
+pgstat_report_relfilenode_buffer_hit(Relation reln)
+{
+ PgStat_StatRelFileNodeEntry *relfileentry = NULL;
+
+ /* For relation stats to survive after a rewrite */
+ pgstat_count_buffer_hit(reln);
+
+ relfileentry = pgstat_prep_relfilenode_pending(reln->rd_locator);
+
+ if (relfileentry)
+ relfileentry->blocks_hit++;
+}
+
/*
* add a new (sub)transaction state record
*/
diff --git a/src/backend/utils/activity/pgstat_replslot.c b/src/backend/utils/activity/pgstat_replslot.c
index 889e86ac5a..96c6621477 100644
--- a/src/backend/utils/activity/pgstat_replslot.c
+++ b/src/backend/utils/activity/pgstat_replslot.c
@@ -62,7 +62,7 @@ pgstat_reset_replslot(const char *name)
*/
if (SlotIsLogical(slot))
pgstat_reset(PGSTAT_KIND_REPLSLOT, InvalidOid,
- ReplicationSlotIndex(slot));
+ ReplicationSlotIndex(slot), InvalidOid);
LWLockRelease(ReplicationSlotControlLock);
}
@@ -82,7 +82,7 @@ pgstat_report_replslot(ReplicationSlot *slot, const PgStat_StatReplSlotEntry *re
PgStat_StatReplSlotEntry *statent;
entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_REPLSLOT, InvalidOid,
- ReplicationSlotIndex(slot), false);
+ ReplicationSlotIndex(slot), InvalidOid, false);
shstatent = (PgStatShared_ReplSlot *) entry_ref->shared_stats;
statent = &shstatent->stats;
@@ -116,7 +116,7 @@ pgstat_create_replslot(ReplicationSlot *slot)
Assert(LWLockHeldByMeInMode(ReplicationSlotAllocationLock, LW_EXCLUSIVE));
entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_REPLSLOT, InvalidOid,
- ReplicationSlotIndex(slot), false);
+ ReplicationSlotIndex(slot), InvalidOid, false);
shstatent = (PgStatShared_ReplSlot *) entry_ref->shared_stats;
/*
@@ -146,7 +146,7 @@ void
pgstat_acquire_replslot(ReplicationSlot *slot)
{
pgstat_get_entry_ref(PGSTAT_KIND_REPLSLOT, InvalidOid,
- ReplicationSlotIndex(slot), true, NULL);
+ ReplicationSlotIndex(slot), InvalidOid, true, NULL);
}
/*
@@ -158,7 +158,7 @@ pgstat_drop_replslot(ReplicationSlot *slot)
Assert(LWLockHeldByMeInMode(ReplicationSlotAllocationLock, LW_EXCLUSIVE));
pgstat_drop_entry(PGSTAT_KIND_REPLSLOT, InvalidOid,
- ReplicationSlotIndex(slot));
+ ReplicationSlotIndex(slot), InvalidOid);
}
/*
@@ -177,7 +177,7 @@ pgstat_fetch_replslot(NameData slotname)
if (idx != -1)
slotentry = (PgStat_StatReplSlotEntry *) pgstat_fetch_entry(PGSTAT_KIND_REPLSLOT,
- InvalidOid, idx);
+ InvalidOid, idx, InvalidOid);
LWLockRelease(ReplicationSlotControlLock);
@@ -209,6 +209,7 @@ pgstat_replslot_from_serialized_name_cb(const NameData *name, PgStat_HashKey *ke
key->kind = PGSTAT_KIND_REPLSLOT;
key->dboid = InvalidOid;
key->objoid = idx;
+ key->relfile = InvalidOid;
return true;
}
diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c
index 91591da395..d74b07e414 100644
--- a/src/backend/utils/activity/pgstat_shmem.c
+++ b/src/backend/utils/activity/pgstat_shmem.c
@@ -395,10 +395,10 @@ pgstat_get_entry_ref_cached(PgStat_HashKey key, PgStat_EntryRef **entry_ref_p)
* if the entry is newly created, false otherwise.
*/
PgStat_EntryRef *
-pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid, bool create,
- bool *created_entry)
+pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile,
+ bool create, bool *created_entry)
{
- PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid};
+ PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid,.relfile = relfile};
PgStatShared_HashEntry *shhashent;
PgStatShared_Common *shheader = NULL;
PgStat_EntryRef *entry_ref;
@@ -611,12 +611,12 @@ pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
*/
PgStat_EntryRef *
pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid,
- bool nowait)
+ RelFileNumber relfile, bool nowait)
{
PgStat_EntryRef *entry_ref;
/* find shared table stats entry corresponding to the local entry */
- entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, true, NULL);
+ entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, relfile, true, NULL);
/* lock the shared entry to protect the content, skip if failed */
if (!pgstat_lock_entry(entry_ref, nowait))
@@ -856,9 +856,9 @@ pgstat_drop_database_and_contents(Oid dboid)
}
bool
-pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
+pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile)
{
- PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid};
+ PgStat_HashKey key = {.kind = kind,.dboid = dboid,.objoid = objoid,.relfile = relfile};
PgStatShared_HashEntry *shent;
bool freed = true;
@@ -931,13 +931,12 @@ shared_stat_reset_contents(PgStat_Kind kind, PgStatShared_Common *header,
* Reset one variable-numbered stats entry.
*/
void
-pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, TimestampTz ts)
+pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile, TimestampTz ts)
{
PgStat_EntryRef *entry_ref;
Assert(!pgstat_get_kind_info(kind)->fixed_amount);
-
- entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, false, NULL);
+ entry_ref = pgstat_get_entry_ref(kind, dboid, objoid, relfile, false, NULL);
if (!entry_ref || entry_ref->shared_entry->dropped)
return;
diff --git a/src/backend/utils/activity/pgstat_subscription.c b/src/backend/utils/activity/pgstat_subscription.c
index d9af8de658..9b9ab2861b 100644
--- a/src/backend/utils/activity/pgstat_subscription.c
+++ b/src/backend/utils/activity/pgstat_subscription.c
@@ -30,7 +30,7 @@ pgstat_report_subscription_error(Oid subid, bool is_apply_error)
PgStat_BackendSubEntry *pending;
entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_SUBSCRIPTION,
- InvalidOid, subid, NULL);
+ InvalidOid, subid, InvalidOid, NULL);
pending = entry_ref->pending;
if (is_apply_error)
@@ -47,12 +47,12 @@ pgstat_create_subscription(Oid subid)
{
/* Ensures that stats are dropped if transaction rolls back */
pgstat_create_transactional(PGSTAT_KIND_SUBSCRIPTION,
- InvalidOid, subid);
+ InvalidOid, subid, InvalidOid);
/* Create and initialize the subscription stats entry */
- pgstat_get_entry_ref(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid,
+ pgstat_get_entry_ref(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid, InvalidOid,
true, NULL);
- pgstat_reset_entry(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid, 0);
+ pgstat_reset_entry(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid, InvalidOid, 0);
}
/*
@@ -64,7 +64,7 @@ void
pgstat_drop_subscription(Oid subid)
{
pgstat_drop_transactional(PGSTAT_KIND_SUBSCRIPTION,
- InvalidOid, subid);
+ InvalidOid, subid, InvalidOid);
}
/*
@@ -75,7 +75,7 @@ PgStat_StatSubEntry *
pgstat_fetch_stat_subscription(Oid subid)
{
return (PgStat_StatSubEntry *)
- pgstat_fetch_entry(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid);
+ pgstat_fetch_entry(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid, InvalidOid);
}
/*
diff --git a/src/backend/utils/activity/pgstat_xact.c b/src/backend/utils/activity/pgstat_xact.c
index 1877d22f14..b25df5112b 100644
--- a/src/backend/utils/activity/pgstat_xact.c
+++ b/src/backend/utils/activity/pgstat_xact.c
@@ -30,7 +30,7 @@ static void AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool
static void AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state,
bool isCommit, int nestDepth);
-static PgStat_SubXactStatus *pgStatXactStack = NULL;
+PgStat_SubXactStatus *pgStatXactStack = NULL;
/*
@@ -84,7 +84,7 @@ AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit)
* Transaction that dropped an object committed. Drop the stats
* too.
*/
- if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
+ if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid, it->relfile))
not_freed_count++;
}
else if (!isCommit && pending->is_create)
@@ -93,7 +93,7 @@ AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit)
* Transaction that created an object aborted. Drop the stats
* associated with the object.
*/
- if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
+ if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid, it->relfile))
not_freed_count++;
}
@@ -105,6 +105,33 @@ AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit)
pgstat_request_entry_refs_gc();
}
+/*
+ * Remove a relfilenode stat from the list of stats to be dropped.
+ */
+void
+PgStat_RemoveRelFileNodeFromDroppedStats(PgStat_SubXactStatus *xact_state, RelFileLocator rlocator)
+{
+ dlist_mutable_iter iter;
+
+ if (dclist_count(&xact_state->pending_drops) == 0)
+ return;
+
+ dclist_foreach_modify(iter, &xact_state->pending_drops)
+ {
+ PgStat_PendingDroppedStatsItem *pending =
+ dclist_container(PgStat_PendingDroppedStatsItem, node, iter.cur);
+ xl_xact_stats_item *it = &pending->item;
+
+ if (it->kind == PGSTAT_KIND_RELFILENODE && it->dboid == rlocator.dbOid
+ && it->objoid == rlocator.spcOid && it->relfile == rlocator.relNumber)
+ {
+ dclist_delete_from(&xact_state->pending_drops, &pending->node);
+ pfree(pending);
+ return;
+ }
+ }
+}
+
/*
* Called from access/transam/xact.c at subtransaction commit/abort.
*/
@@ -158,7 +185,7 @@ AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state,
* Subtransaction creating a new stats object aborted. Drop the
* stats object.
*/
- if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
+ if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid, it->relfile))
not_freed_count++;
pfree(pending);
}
@@ -320,7 +347,11 @@ pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items,
{
xl_xact_stats_item *it = &items[i];
- if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
+ /* leave it to pgstat_drop_transactional() in RelationDropStorage() */
+ if (it->kind == PGSTAT_KIND_RELFILENODE)
+ continue;
+
+ if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid, it->relfile))
not_freed_count++;
}
@@ -329,7 +360,7 @@ pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items,
}
static void
-create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool is_create)
+create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile, bool is_create)
{
int nest_level = GetCurrentTransactionNestLevel();
PgStat_SubXactStatus *xact_state;
@@ -342,6 +373,7 @@ create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool
drop->item.kind = kind;
drop->item.dboid = dboid;
drop->item.objoid = objoid;
+ drop->item.relfile = relfile;
dclist_push_tail(&xact_state->pending_drops, &drop->node);
}
@@ -354,18 +386,18 @@ create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool
* dropped.
*/
void
-pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
+pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile)
{
- if (pgstat_get_entry_ref(kind, dboid, objoid, false, NULL))
+ if (pgstat_get_entry_ref(kind, dboid, objoid, relfile, false, NULL))
{
ereport(WARNING,
- errmsg("resetting existing statistics for kind %s, db=%u, oid=%u",
- (pgstat_get_kind_info(kind))->name, dboid, objoid));
+ errmsg("resetting existing statistics for kind %s, db=%u, oid=%u, relfile=%u",
+ (pgstat_get_kind_info(kind))->name, dboid, objoid, relfile));
- pgstat_reset(kind, dboid, objoid);
+ pgstat_reset(kind, dboid, objoid, relfile);
}
- create_drop_transactional_internal(kind, dboid, objoid, /* create */ true);
+ create_drop_transactional_internal(kind, dboid, objoid, relfile, /* create */ true);
}
/*
@@ -376,7 +408,7 @@ pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
* alive.
*/
void
-pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
+pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile)
{
- create_drop_transactional_internal(kind, dboid, objoid, /* create */ false);
+ create_drop_transactional_internal(kind, dboid, objoid, relfile, /* create */ false);
}
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 3876339ee1..e266d96f5e 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -106,6 +106,30 @@ PG_STAT_GET_RELENTRY_INT64(tuples_updated)
/* pg_stat_get_vacuum_count */
PG_STAT_GET_RELENTRY_INT64(vacuum_count)
+#define PG_STAT_GET_RELFILEENTRY_INT64(stat) \
+Datum \
+CppConcat(pg_stat_get_relfilenode_,stat)(PG_FUNCTION_ARGS) \
+{ \
+ Oid dboid = PG_GETARG_OID(0); \
+ Oid spcOid = PG_GETARG_OID(1); \
+ RelFileNumber relfile = PG_GETARG_OID(2); \
+ int64 result; \
+ PgStat_StatRelFileNodeEntry *relfileentry; \
+ \
+ if ((relfileentry = pgstat_fetch_stat_relfilenodeentry(dboid, spcOid, relfile)) == NULL) \
+ result = 0; \
+ else \
+ result = (int64) (relfileentry->stat); \
+ \
+ PG_RETURN_INT64(result); \
+}
+
+/* pg_stat_get_relfilenode_blocks_written */
+PG_STAT_GET_RELFILEENTRY_INT64(blocks_written)
+
+/* pg_stat_get_blocks_written */
+PG_STAT_GET_RELENTRY_INT64(blocks_written)
+
#define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(stat) \
Datum \
CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS) \
@@ -1752,7 +1776,7 @@ pg_stat_reset_single_table_counters(PG_FUNCTION_ARGS)
Oid taboid = PG_GETARG_OID(0);
Oid dboid = (IsSharedRelation(taboid) ? InvalidOid : MyDatabaseId);
- pgstat_reset(PGSTAT_KIND_RELATION, dboid, taboid);
+ pgstat_reset(PGSTAT_KIND_RELATION, dboid, taboid, InvalidOid);
PG_RETURN_VOID();
}
@@ -1762,7 +1786,7 @@ pg_stat_reset_single_function_counters(PG_FUNCTION_ARGS)
{
Oid funcoid = PG_GETARG_OID(0);
- pgstat_reset(PGSTAT_KIND_FUNCTION, MyDatabaseId, funcoid);
+ pgstat_reset(PGSTAT_KIND_FUNCTION, MyDatabaseId, funcoid, InvalidOid);
PG_RETURN_VOID();
}
@@ -1820,7 +1844,7 @@ pg_stat_reset_subscription_stats(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid subscription OID %u", subid)));
- pgstat_reset(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid);
+ pgstat_reset(PGSTAT_KIND_SUBSCRIPTION, InvalidOid, subid, InvalidOid);
}
PG_RETURN_VOID();
@@ -2028,7 +2052,9 @@ pg_stat_have_stats(PG_FUNCTION_ARGS)
char *stats_type = text_to_cstring(PG_GETARG_TEXT_P(0));
Oid dboid = PG_GETARG_OID(1);
Oid objoid = PG_GETARG_OID(2);
+ Oid relfile = PG_GETARG_OID(3);
+
PgStat_Kind kind = pgstat_get_kind_from_str(stats_type);
- PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid));
+ PG_RETURN_BOOL(pgstat_have_entry(kind, dboid, objoid, relfile));
}
diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h
index 8e583b45cd..792cd2237e 100644
--- a/src/include/access/tableam.h
+++ b/src/include/access/tableam.h
@@ -21,7 +21,9 @@
#include "access/sdir.h"
#include "access/xact.h"
#include "executor/tuptable.h"
+#include "pgstat.h"
#include "storage/read_stream.h"
+#include "utils/pgstat_internal.h"
#include "utils/rel.h"
#include "utils/snapshot.h"
@@ -1634,6 +1636,23 @@ table_relation_set_new_filelocator(Relation rel,
TransactionId *freezeXid,
MultiXactId *minmulti)
{
+ PgStat_StatRelFileNodeEntry *relfileentry;
+ PgStat_StatTabEntry *tabentry = NULL;
+ PgStat_EntryRef *entry_ref = NULL;
+ PgStatShared_Relation *shtabentry;
+
+ entry_ref = pgstat_get_entry_ref(PGSTAT_KIND_RELATION, MyDatabaseId, rel->rd_id, InvalidOid, false, NULL);
+ if (entry_ref)
+ {
+ shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
+ tabentry = &shtabentry->stats;
+ }
+
+ relfileentry = pgstat_fetch_stat_relfilenodeentry(rel->rd_locator.dbOid, rel->rd_locator.spcOid, rel->rd_locator.relNumber);
+
+ if (tabentry && relfileentry)
+ tabentry->blocks_written += relfileentry->blocks_written;
+
rel->rd_tableam->relation_set_new_filelocator(rel, newrlocator,
persistence, freezeXid,
minmulti);
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 6d4439f052..3b9ed65ff6 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -284,6 +284,7 @@ typedef struct xl_xact_stats_item
int kind;
Oid dboid;
Oid objoid;
+ RelFileNumber relfile;
} xl_xact_stats_item;
typedef struct xl_xact_stats_items
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 6a5476d3c4..912471a1ac 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5374,6 +5374,14 @@
proname => 'pg_stat_get_tuples_updated', provolatile => 's',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_tuples_updated' },
+{ oid => '9280', descr => 'statistics: number of blocks written',
+ proname => 'pg_stat_get_relfilenode_blocks_written', provolatile => 's',
+ proparallel => 'r',
+ proargtypes => 'oid oid oid',
+ prorettype => 'int8',
+ proallargtypes => '{oid,oid,oid,int8}',
+ proargmodes => '{i,i,i,o}',
+ prosrc => 'pg_stat_get_relfilenode_blocks_written' },
{ oid => '1933', descr => 'statistics: number of tuples deleted',
proname => 'pg_stat_get_tuples_deleted', provolatile => 's',
proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
@@ -5413,6 +5421,10 @@
proname => 'pg_stat_get_blocks_hit', provolatile => 's', proparallel => 'r',
prorettype => 'int8', proargtypes => 'oid',
prosrc => 'pg_stat_get_blocks_hit' },
+{ oid => '8438', descr => 'statistics: number of blocks written',
+ proname => 'pg_stat_get_blocks_written', provolatile => 's', proparallel => 'r',
+ prorettype => 'int8', proargtypes => 'oid',
+ prosrc => 'pg_stat_get_blocks_written' },
{ oid => '2781', descr => 'statistics: last manual vacuum time for a table',
proname => 'pg_stat_get_last_vacuum_time', provolatile => 's',
proparallel => 'r', prorettype => 'timestamptz', proargtypes => 'oid',
@@ -5499,7 +5511,7 @@
{ oid => '6230', descr => 'statistics: check if a stats object exists',
proname => 'pg_stat_have_stats', provolatile => 'v', proparallel => 'r',
- prorettype => 'bool', proargtypes => 'text oid oid',
+ prorettype => 'bool', proargtypes => 'text oid oid oid',
prosrc => 'pg_stat_have_stats' },
{ oid => '6231', descr => 'statistics: information about subscription stats',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 2136239710..9631689430 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -14,6 +14,7 @@
#include "datatype/timestamp.h"
#include "portability/instr_time.h"
#include "postmaster/pgarch.h" /* for MAX_XFN_CHARS */
+#include "storage/relfilelocator.h"
#include "utils/backend_progress.h" /* for backward compatibility */
#include "utils/backend_status.h" /* for backward compatibility */
#include "utils/relcache.h"
@@ -40,6 +41,7 @@ typedef enum PgStat_Kind
/* stats for variable-numbered objects */
PGSTAT_KIND_DATABASE, /* database-wide statistics */
PGSTAT_KIND_RELATION, /* per-table statistics */
+ PGSTAT_KIND_RELFILENODE, /* per-relfilenode statistics */
PGSTAT_KIND_FUNCTION, /* per-function statistics */
PGSTAT_KIND_REPLSLOT, /* per-slot statistics */
PGSTAT_KIND_SUBSCRIPTION, /* per-subscription statistics */
@@ -417,6 +419,7 @@ typedef struct PgStat_StatTabEntry
PgStat_Counter blocks_fetched;
PgStat_Counter blocks_hit;
+ PgStat_Counter blocks_written;
TimestampTz last_vacuum_time; /* user initiated vacuum */
PgStat_Counter vacuum_count;
@@ -428,6 +431,13 @@ typedef struct PgStat_StatTabEntry
PgStat_Counter autoanalyze_count;
} PgStat_StatTabEntry;
+typedef struct PgStat_StatRelFileNodeEntry
+{
+ PgStat_Counter blocks_fetched;
+ PgStat_Counter blocks_hit;
+ PgStat_Counter blocks_written;
+} PgStat_StatRelFileNodeEntry;
+
typedef struct PgStat_WalStats
{
PgStat_Counter wal_records;
@@ -478,7 +488,7 @@ extern long pgstat_report_stat(bool force);
extern void pgstat_force_next_flush(void);
extern void pgstat_reset_counters(void);
-extern void pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern void pgstat_reset(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile);
extern void pgstat_reset_of_kind(PgStat_Kind kind);
/* stats accessors */
@@ -487,7 +497,7 @@ extern TimestampTz pgstat_get_stat_snapshot_timestamp(bool *have_snapshot);
/* helpers */
extern PgStat_Kind pgstat_get_kind_from_str(char *kind_str);
-extern bool pgstat_have_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern bool pgstat_have_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile);
/*
@@ -596,6 +606,10 @@ extern void pgstat_report_analyze(Relation rel,
PgStat_Counter livetuples, PgStat_Counter deadtuples,
bool resetcounter);
+extern void pgstat_report_relfilenode_blks_written(RelFileLocator locator);
+extern void pgstat_report_relfilenode_buffer_read(Relation reln);
+extern void pgstat_report_relfilenode_buffer_hit(Relation reln);
+
/*
* If stats are enabled, but pending data hasn't been prepared yet, call
* pgstat_assoc_relation() to do so. See its comment for why this is done
@@ -655,6 +669,7 @@ extern void pgstat_twophase_postabort(TransactionId xid, uint16 info,
void *recdata, uint32 len);
extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
+extern PgStat_StatRelFileNodeEntry *pgstat_fetch_stat_relfilenodeentry(Oid dboid, Oid spcOid, RelFileNumber relfile);
extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry_ext(bool shared,
Oid reloid);
extern PgStat_TableStatus *find_tabstat_entry(Oid rel_id);
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index dbbca31602..50d5f1a577 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -53,7 +53,8 @@ typedef struct PgStat_HashKey
{
PgStat_Kind kind; /* statistics entry kind */
Oid dboid; /* database ID. InvalidOid for shared objects. */
- Oid objoid; /* object ID, either table or function. */
+ Oid objoid; /* object ID, either table or function or tablespace. */
+ RelFileNumber relfile; /* relfilenumber for RelFileLocator. */
} PgStat_HashKey;
/*
@@ -376,6 +377,12 @@ typedef struct PgStatShared_Relation
PgStat_StatTabEntry stats;
} PgStatShared_Relation;
+typedef struct PgStatShared_RelFileNode
+{
+ PgStatShared_Common header;
+ PgStat_StatRelFileNodeEntry stats;
+} PgStatShared_RelFileNode;
+
typedef struct PgStatShared_Function
{
PgStatShared_Common header;
@@ -498,6 +505,9 @@ static inline size_t pgstat_get_entry_len(PgStat_Kind kind);
static inline void *pgstat_get_entry_data(PgStat_Kind kind, PgStatShared_Common *entry);
+extern PgStat_SubXactStatus *pgStatXactStack;
+extern void PgStat_RemoveRelFileNodeFromDroppedStats(PgStat_SubXactStatus *xact_state, RelFileLocator rlocator);
+
/*
* Functions in pgstat.c
*/
@@ -511,10 +521,12 @@ extern void pgstat_assert_is_up(void);
#endif
extern void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref);
-extern PgStat_EntryRef *pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, bool *created_entry);
-extern PgStat_EntryRef *pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern PgStat_EntryRef *pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid,
+ Oid objoid, RelFileNumber relfile,
+ bool *created_entry);
+extern PgStat_EntryRef *pgstat_fetch_pending_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile);
-extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern void *pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile);
extern void pgstat_snapshot_fixed(PgStat_Kind kind);
@@ -582,6 +594,7 @@ extern void AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
extern void PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state);
extern bool pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+extern bool pgstat_relfilenode_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
extern void pgstat_relation_delete_pending_cb(PgStat_EntryRef *entry_ref);
@@ -602,15 +615,16 @@ extern void pgstat_attach_shmem(void);
extern void pgstat_detach_shmem(void);
extern PgStat_EntryRef *pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, Oid objoid,
- bool create, bool *created_entry);
+ RelFileNumber relfile, bool create,
+ bool *created_entry);
extern bool pgstat_lock_entry(PgStat_EntryRef *entry_ref, bool nowait);
extern bool pgstat_lock_entry_shared(PgStat_EntryRef *entry_ref, bool nowait);
extern void pgstat_unlock_entry(PgStat_EntryRef *entry_ref);
-extern bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile);
extern void pgstat_drop_all_entries(void);
extern PgStat_EntryRef *pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, Oid objoid,
- bool nowait);
-extern void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, TimestampTz ts);
+ RelFileNumber relfile, bool nowait);
+extern void pgstat_reset_entry(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile, TimestampTz ts);
extern void pgstat_reset_entries_of_kind(PgStat_Kind kind, TimestampTz ts);
extern void pgstat_reset_matching_entries(bool (*do_reset) (PgStatShared_HashEntry *, Datum),
Datum match_data,
@@ -655,8 +669,8 @@ extern void pgstat_subscription_reset_timestamp_cb(PgStatShared_Common *header,
*/
extern PgStat_SubXactStatus *pgstat_get_xact_stack_level(int nest_level);
-extern void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid);
-extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid);
+extern void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile);
+extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid, RelFileNumber relfile);
/*
diff --git a/src/test/recovery/t/029_stats_restart.pl b/src/test/recovery/t/029_stats_restart.pl
index 6a1615a1e8..ee5a404b45 100644
--- a/src/test/recovery/t/029_stats_restart.pl
+++ b/src/test/recovery/t/029_stats_restart.pl
@@ -40,10 +40,10 @@ trigger_funcrel_stat();
# verify stats objects exist
my $sect = "initial";
-is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
-is(have_stats('function', $dboid, $funcoid),
+is(have_stats('database', $dboid, 0, 0), 't', "$sect: db stats do exist");
+is(have_stats('function', $dboid, $funcoid, 0),
't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
+is(have_stats('relation', $dboid, $tableoid, 0),
't', "$sect: relation stats do exist");
# regular shutdown
@@ -64,10 +64,10 @@ copy($og_stats, $statsfile) or die "Copy failed: $!";
$node->start;
$sect = "copy";
-is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
-is(have_stats('function', $dboid, $funcoid),
+is(have_stats('database', $dboid, 0, 0), 't', "$sect: db stats do exist");
+is(have_stats('function', $dboid, $funcoid, 0),
't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
+is(have_stats('relation', $dboid, $tableoid, 0),
't', "$sect: relation stats do exist");
$node->stop('immediate');
@@ -81,10 +81,10 @@ $node->start;
# stats should have been discarded
$sect = "post immediate";
-is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
-is(have_stats('function', $dboid, $funcoid),
+is(have_stats('database', $dboid, 0, 0), 'f', "$sect: db stats do not exist");
+is(have_stats('function', $dboid, $funcoid, 0),
'f', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
+is(have_stats('relation', $dboid, $tableoid, 0),
'f', "$sect: relation stats do not exist");
# get rid of backup statsfile
@@ -95,10 +95,10 @@ unlink $statsfile or die "cannot unlink $statsfile $!";
trigger_funcrel_stat();
$sect = "post immediate, new";
-is(have_stats('database', $dboid, 0), 't', "$sect: db stats do exist");
-is(have_stats('function', $dboid, $funcoid),
+is(have_stats('database', $dboid, 0, 0), 't', "$sect: db stats do exist");
+is(have_stats('function', $dboid, $funcoid, 0),
't', "$sect: function stats do exist");
-is(have_stats('relation', $dboid, $tableoid),
+is(have_stats('relation', $dboid, $tableoid, 0),
't', "$sect: relation stats do exist");
# regular shutdown
@@ -114,10 +114,10 @@ $node->start;
# no stats present due to invalid stats file
$sect = "invalid_overwrite";
-is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
-is(have_stats('function', $dboid, $funcoid),
+is(have_stats('database', $dboid, 0, 0), 'f', "$sect: db stats do not exist");
+is(have_stats('function', $dboid, $funcoid, 0),
'f', "$sect: function stats do not exist");
-is(have_stats('relation', $dboid, $tableoid),
+is(have_stats('relation', $dboid, $tableoid, 0),
'f', "$sect: relation stats do not exist");
@@ -130,10 +130,10 @@ append_file($og_stats, "XYZ");
$node->start;
$sect = "invalid_append";
-is(have_stats('database', $dboid, 0), 'f', "$sect: db stats do not exist");
-is(have_stats('function', $dboid, $funcoid),
+is(have_stats('database', $dboid, 0, 0), 'f', "$sect: db stats do not exist");
+is(have_stats('function', $dboid, $funcoid, 0),
'f', "$sect: function stats do not exist");
-is(have_stats('relation', $dboid, $tableoid),
+is(have_stats('relation', $dboid, $tableoid, 0),
'f', "$sect: relation stats do not exist");
@@ -292,10 +292,10 @@ sub trigger_funcrel_stat
sub have_stats
{
- my ($kind, $dboid, $objoid) = @_;
+ my ($kind, $dboid, $objoid, $relfile) = @_;
return $node->safe_psql($connect_db,
- "SELECT pg_stat_have_stats('$kind', $dboid, $objoid)");
+ "SELECT pg_stat_have_stats('$kind', $dboid, $objoid, $relfile)");
}
sub overwrite_file
diff --git a/src/test/recovery/t/030_stats_cleanup_replica.pl b/src/test/recovery/t/030_stats_cleanup_replica.pl
index 74b516cc7c..317df24c4f 100644
--- a/src/test/recovery/t/030_stats_cleanup_replica.pl
+++ b/src/test/recovery/t/030_stats_cleanup_replica.pl
@@ -179,9 +179,9 @@ sub test_standby_func_tab_stats_status
my %stats;
$stats{rel} = $node_standby->safe_psql($connect_db,
- "SELECT pg_stat_have_stats('relation', $dboid, $tableoid)");
+ "SELECT pg_stat_have_stats('relation', $dboid, $tableoid, 0)");
$stats{func} = $node_standby->safe_psql($connect_db,
- "SELECT pg_stat_have_stats('function', $dboid, $funcoid)");
+ "SELECT pg_stat_have_stats('function', $dboid, $funcoid, 0)");
is_deeply(\%stats, \%expected, "$sect: standby stats as expected");
@@ -194,7 +194,7 @@ sub test_standby_db_stats_status
my ($connect_db, $dboid, $present) = @_;
is( $node_standby->safe_psql(
- $connect_db, "SELECT pg_stat_have_stats('database', $dboid, 0)"),
+ $connect_db, "SELECT pg_stat_have_stats('database', $dboid, 0, 0)"),
$present,
"$sect: standby db stats as expected");
}
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index ef658ad740..a2fa165c4c 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2335,6 +2335,11 @@ pg_statio_all_tables| SELECT c.oid AS relid,
n.nspname AS schemaname,
c.relname,
(pg_stat_get_blocks_fetched(c.oid) - pg_stat_get_blocks_hit(c.oid)) AS heap_blks_read,
+ (pg_stat_get_blocks_written(c.oid) + pg_stat_get_relfilenode_blocks_written(d.oid,
+ CASE
+ WHEN (c.reltablespace <> (0)::oid) THEN c.reltablespace
+ ELSE d.dattablespace
+ END, c.relfilenode)) AS heap_blks_written,
pg_stat_get_blocks_hit(c.oid) AS heap_blks_hit,
i.idx_blks_read,
i.idx_blks_hit,
@@ -2342,7 +2347,8 @@ pg_statio_all_tables| SELECT c.oid AS relid,
pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit,
x.idx_blks_read AS tidx_blks_read,
x.idx_blks_hit AS tidx_blks_hit
- FROM ((((pg_class c
+ FROM pg_database d,
+ ((((pg_class c
LEFT JOIN pg_class t ON ((c.reltoastrelid = t.oid)))
LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
LEFT JOIN LATERAL ( SELECT (sum((pg_stat_get_blocks_fetched(pg_index.indexrelid) - pg_stat_get_blocks_hit(pg_index.indexrelid))))::bigint AS idx_blks_read,
@@ -2353,7 +2359,7 @@ pg_statio_all_tables| SELECT c.oid AS relid,
(sum(pg_stat_get_blocks_hit(pg_index.indexrelid)))::bigint AS idx_blks_hit
FROM pg_index
WHERE (pg_index.indrelid = t.oid)) x ON (true))
- WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"]));
+ WHERE ((c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"])) AND (d.datname = current_database()));
pg_statio_sys_indexes| SELECT relid,
indexrelid,
schemaname,
@@ -2374,6 +2380,7 @@ pg_statio_sys_tables| SELECT relid,
schemaname,
relname,
heap_blks_read,
+ heap_blks_written,
heap_blks_hit,
idx_blks_read,
idx_blks_hit,
@@ -2403,6 +2410,7 @@ pg_statio_user_tables| SELECT relid,
schemaname,
relname,
heap_blks_read,
+ heap_blks_written,
heap_blks_hit,
idx_blks_read,
idx_blks_hit,
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 6e08898b18..eff0c9372c 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1111,23 +1111,23 @@ ROLLBACK;
-- pg_stat_have_stats behavior
----
-- fixed-numbered stats exist
-SELECT pg_stat_have_stats('bgwriter', 0, 0);
+SELECT pg_stat_have_stats('bgwriter', 0, 0, 0);
pg_stat_have_stats
--------------------
t
(1 row)
-- unknown stats kinds error out
-SELECT pg_stat_have_stats('zaphod', 0, 0);
+SELECT pg_stat_have_stats('zaphod', 0, 0, 0);
ERROR: invalid statistics kind: "zaphod"
-- db stats have objoid 0
-SELECT pg_stat_have_stats('database', :dboid, 1);
+SELECT pg_stat_have_stats('database', :dboid, 1, 0);
pg_stat_have_stats
--------------------
f
(1 row)
-SELECT pg_stat_have_stats('database', :dboid, 0);
+SELECT pg_stat_have_stats('database', :dboid, 0, 0);
pg_stat_have_stats
--------------------
t
@@ -1144,21 +1144,21 @@ select a from stats_test_tab1 where a = 3;
3
(1 row)
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
t
(1 row)
-- pg_stat_have_stats returns false for dropped index with stats
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
t
(1 row)
DROP index stats_test_idx1;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
f
@@ -1174,14 +1174,14 @@ select a from stats_test_tab1 where a = 3;
3
(1 row)
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
t
(1 row)
ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
f
@@ -1196,7 +1196,7 @@ select a from stats_test_tab1 where a = 3;
3
(1 row)
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
t
@@ -1204,7 +1204,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
REINDEX index CONCURRENTLY stats_test_idx1;
-- false for previous oid
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
f
@@ -1212,7 +1212,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
-- true for new oid
SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
t
@@ -1220,7 +1220,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
-- pg_stat_have_stats returns true for a rolled back drop index with stats
BEGIN;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
t
@@ -1228,7 +1228,7 @@ SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
DROP index stats_test_idx1;
ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
pg_stat_have_stats
--------------------
t
@@ -1513,7 +1513,7 @@ SELECT :io_sum_bulkwrite_strategy_extends_after > :io_sum_bulkwrite_strategy_ext
(1 row)
-- Test IO stats reset
-SELECT pg_stat_have_stats('io', 0, 0);
+SELECT pg_stat_have_stats('io', 0, 0, 0);
pg_stat_have_stats
--------------------
t
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index d8ac0d06f4..5a40779989 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -539,12 +539,12 @@ ROLLBACK;
-- pg_stat_have_stats behavior
----
-- fixed-numbered stats exist
-SELECT pg_stat_have_stats('bgwriter', 0, 0);
+SELECT pg_stat_have_stats('bgwriter', 0, 0, 0);
-- unknown stats kinds error out
-SELECT pg_stat_have_stats('zaphod', 0, 0);
+SELECT pg_stat_have_stats('zaphod', 0, 0, 0);
-- db stats have objoid 0
-SELECT pg_stat_have_stats('database', :dboid, 1);
-SELECT pg_stat_have_stats('database', :dboid, 0);
+SELECT pg_stat_have_stats('database', :dboid, 1, 0);
+SELECT pg_stat_have_stats('database', :dboid, 0, 0);
-- pg_stat_have_stats returns true for committed index creation
CREATE table stats_test_tab1 as select generate_series(1,10) a;
@@ -552,40 +552,40 @@ CREATE index stats_test_idx1 on stats_test_tab1(a);
SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
SET enable_seqscan TO off;
select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
-- pg_stat_have_stats returns false for dropped index with stats
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
DROP index stats_test_idx1;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
-- pg_stat_have_stats returns false for rolled back index creation
BEGIN;
CREATE index stats_test_idx1 on stats_test_tab1(a);
SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
-- pg_stat_have_stats returns true for reindex CONCURRENTLY
CREATE index stats_test_idx1 on stats_test_tab1(a);
SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
select a from stats_test_tab1 where a = 3;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
REINDEX index CONCURRENTLY stats_test_idx1;
-- false for previous oid
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
-- true for new oid
SELECT 'stats_test_idx1'::regclass::oid AS stats_test_idx1_oid \gset
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
-- pg_stat_have_stats returns true for a rolled back drop index with stats
BEGIN;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
DROP index stats_test_idx1;
ROLLBACK;
-SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid);
+SELECT pg_stat_have_stats('relation', :dboid, :stats_test_idx1_oid, 0);
-- put enable_seqscan back to on
SET enable_seqscan TO on;
@@ -759,7 +759,7 @@ SELECT sum(extends) AS io_sum_bulkwrite_strategy_extends_after
SELECT :io_sum_bulkwrite_strategy_extends_after > :io_sum_bulkwrite_strategy_extends_before;
-- Test IO stats reset
-SELECT pg_stat_have_stats('io', 0, 0);
+SELECT pg_stat_have_stats('io', 0, 0, 0);
SELECT sum(evictions) + sum(reuses) + sum(extends) + sum(fsyncs) + sum(reads) + sum(writes) + sum(writebacks) + sum(hits) AS io_stats_pre_reset
FROM pg_stat_io \gset
SELECT pg_stat_reset_shared('io');
diff --git a/src/test/subscription/t/026_stats.pl b/src/test/subscription/t/026_stats.pl
index fb3e5629b3..1f4ae5efd5 100644
--- a/src/test/subscription/t/026_stats.pl
+++ b/src/test/subscription/t/026_stats.pl
@@ -263,7 +263,7 @@ $node_subscriber->safe_psql($db, qq(DROP SUBSCRIPTION $sub1_name));
# Subscription stats for sub1 should be gone
is( $node_subscriber->safe_psql(
- $db, qq(SELECT pg_stat_have_stats('subscription', 0, $sub1_oid))),
+ $db, qq(SELECT pg_stat_have_stats('subscription', 0, $sub1_oid, 0))),
qq(f),
qq(Subscription stats for subscription '$sub1_name' should be removed.));
@@ -282,7 +282,7 @@ DROP SUBSCRIPTION $sub2_name;
# Subscription stats for sub2 should be gone
is( $node_subscriber->safe_psql(
- $db, qq(SELECT pg_stat_have_stats('subscription', 0, $sub2_oid))),
+ $db, qq(SELECT pg_stat_have_stats('subscription', 0, $sub2_oid, 0))),
qq(f),
qq(Subscription stats for subscription '$sub2_name' should be removed.));
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index d427a1c16a..d7385f9bfb 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2118,6 +2118,7 @@ PgStatShared_Function
PgStatShared_HashEntry
PgStatShared_IO
PgStatShared_Relation
+PgStatShared_RelFileNode
PgStatShared_ReplSlot
PgStatShared_SLRU
PgStatShared_Subscription
--
2.34.1
--TqZvpUxcxjengx0M--
view thread (1606+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH v1] Provide relfilenode statistics
In-Reply-To: <no-message-id-189878@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox