Skip to content

Commit 1cf6c0b

Browse files
author
Commitfest Bot
committed
[CF 5958] v3 - Per backend relation statistics tracking
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5958 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/[email protected] Author(s): Bertrand Drouvot
2 parents e1a912c + 33dedf1 commit 1cf6c0b

File tree

12 files changed

+261
-2
lines changed

12 files changed

+261
-2
lines changed

doc/src/sgml/monitoring.sgml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,19 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
320320
</entry>
321321
</row>
322322

323+
<row>
324+
<entry>
325+
<structname>pg_stat_backend_relation</structname>
326+
<indexterm><primary>pg_stat_backend_relation</primary></indexterm>
327+
</entry>
328+
<entry>
329+
One row per server process, showing relation statistics related to
330+
the current activity of that process, such as number of sequential scans.
331+
See <link linkend="monitoring-pg-stat-backend-relation-view">
332+
<structname>pg_stat_backend_relation</structname></link> for details.
333+
</entry>
334+
</row>
335+
323336
<row>
324337
<entry><structname>pg_stat_replication</structname><indexterm><primary>pg_stat_replication</primary></indexterm></entry>
325338
<entry>One row per WAL sender process, showing statistics about
@@ -1172,6 +1185,72 @@ description | Waiting for a newly initialized WAL file to reach durable storage
11721185
</note>
11731186
</sect2>
11741187

1188+
<sect2 id="monitoring-pg-stat-backend-relation-view">
1189+
<title><structname>pg_stat_backend_relation</structname></title>
1190+
1191+
<indexterm>
1192+
<primary>pg_stat_backend_relation</primary>
1193+
</indexterm>
1194+
1195+
<para>
1196+
The <structname>pg_stat_backend_relation</structname> view will have one row
1197+
per server process, showing relation statistics related to
1198+
the current activity of that process.
1199+
</para>
1200+
1201+
<table id="pg-stat-backend-relation-view" xreflabel="pg_stat_backend_relation">
1202+
<title><structname>pg_stat_backend_relation</structname> View</title>
1203+
<tgroup cols="1">
1204+
<thead>
1205+
<row>
1206+
<entry role="catalog_table_entry"><para role="column_definition">
1207+
Column Type
1208+
</para>
1209+
<para>
1210+
Description
1211+
</para></entry>
1212+
</row>
1213+
</thead>
1214+
1215+
<tbody>
1216+
<row>
1217+
<entry role="catalog_table_entry"><para role="column_definition">
1218+
<structfield>pid</structfield> <type>integer</type>
1219+
</para>
1220+
<para>
1221+
Process ID of this backend
1222+
</para></entry>
1223+
</row>
1224+
1225+
<row>
1226+
<entry role="catalog_table_entry"><para role="column_definition">
1227+
<structfield>seq_scan</structfield> <type>bigint</type>
1228+
</para>
1229+
<para>
1230+
The number of sequential scans initiated on tables.
1231+
</para></entry>
1232+
</row>
1233+
1234+
<row>
1235+
<entry role="catalog_table_entry"><para role="column_definition">
1236+
<structfield>stats_reset</structfield> <type>timestamp with time zone</type>
1237+
</para>
1238+
<para>
1239+
Time at which these statistics were last reset
1240+
</para></entry>
1241+
</row>
1242+
</tbody>
1243+
</tgroup>
1244+
</table>
1245+
1246+
<note>
1247+
<para>
1248+
The view does not return statistics for the checkpointer,
1249+
the background writer, the startup process and the autovacuum launcher.
1250+
</para>
1251+
</note>
1252+
</sect2>
1253+
11751254
<sect2 id="monitoring-pg-stat-replication-view">
11761255
<title><structname>pg_stat_replication</structname></title>
11771256

@@ -4981,6 +5060,22 @@ description | Waiting for a newly initialized WAL file to reach durable storage
49815060
</para></entry>
49825061
</row>
49835062

5063+
<row>
5064+
<entry role="func_table_entry"><para role="func_signature">
5065+
<indexterm>
5066+
<primary>pg_stat_get_backend_relations</primary>
5067+
</indexterm>
5068+
<function>pg_stat_get_backend_relations</function> ( <type>integer</type> )
5069+
<returnvalue>setof record</returnvalue>
5070+
</para>
5071+
<para>
5072+
Returns a record of statistics about the backend with the specified
5073+
process ID, or one record for each active backend in the system
5074+
if <literal>NULL</literal> is specified. The fields returned are a
5075+
subset of those in the <structname>pg_stat_backend_relation</structname> view.
5076+
</para></entry>
5077+
</row>
5078+
49845079
<row>
49855080
<entry id="pg-stat-get-backend-wal" role="func_table_entry"><para role="func_signature">
49865081
<indexterm>

src/backend/catalog/system_views.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,13 @@ CREATE VIEW pg_stat_activity AS
925925
LEFT JOIN pg_database AS D ON (S.datid = D.oid)
926926
LEFT JOIN pg_authid AS U ON (S.usesysid = U.oid);
927927

928+
CREATE VIEW pg_stat_backend_relation AS
929+
SELECT
930+
S.pid,
931+
S.seq_scan,
932+
S.stats_reset
933+
FROM pg_stat_get_backend_relations(NULL) AS S;
934+
928935
CREATE VIEW pg_stat_replication AS
929936
SELECT
930937
S.pid,

src/backend/utils/activity/pgstat_backend.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* reported within critical sections so we use static memory in order to avoid
3838
* memory allocation.
3939
*/
40-
static PgStat_BackendPending PendingBackendStats;
40+
PgStat_BackendPending PendingBackendStats;
4141
static bool backend_has_iostats = false;
4242

4343
/*
@@ -48,6 +48,11 @@ static bool backend_has_iostats = false;
4848
*/
4949
static WalUsage prevBackendWalUsage;
5050

51+
/*
52+
* For backend relations's related statistics.
53+
*/
54+
bool backend_has_relstats = false;
55+
5156
/*
5257
* Utility routines to report I/O stats for backends, kept here to avoid
5358
* exposing PendingBackendStats to the outside world.
@@ -260,6 +265,39 @@ pgstat_flush_backend_entry_wal(PgStat_EntryRef *entry_ref)
260265
prevBackendWalUsage = pgWalUsage;
261266
}
262267

268+
/*
269+
* Flush out locally pending backend relations's related statistics. Locking is
270+
* managed by the caller.
271+
*/
272+
static void
273+
pgstat_flush_backend_entry_rel(PgStat_EntryRef *entry_ref)
274+
{
275+
PgStatShared_Backend *shbackendent;
276+
277+
/*
278+
* This function can be called even if nothing at all has happened for
279+
* relations's related statistics. In this case, avoid unnecessarily
280+
* modifying the stats entry.
281+
*/
282+
if (!backend_has_relstats)
283+
return;
284+
285+
shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats;
286+
287+
#define BACKENDREL_ACC(stat) \
288+
(shbackendent->stats.stat += PendingBackendStats.pending_backendrel.stat)
289+
290+
BACKENDREL_ACC(heap_scan);
291+
#undef BACKENDREL_ACC
292+
293+
/*
294+
* Clear out the statistics buffer, so it can be re-used.
295+
*/
296+
MemSet(&PendingBackendStats.pending_backendrel, 0, sizeof(PgStat_BackendRelPending));
297+
298+
backend_has_relstats = false;
299+
}
300+
263301
/*
264302
* Flush out locally pending backend statistics
265303
*
@@ -284,6 +322,10 @@ pgstat_flush_backend(bool nowait, bits32 flags)
284322
pgstat_backend_wal_have_pending())
285323
has_pending_data = true;
286324

325+
/* Some relations related data pending? */
326+
if ((flags & PGSTAT_BACKEND_FLUSH_REL) && backend_has_relstats)
327+
has_pending_data = true;
328+
287329
if (!has_pending_data)
288330
return false;
289331

@@ -299,6 +341,9 @@ pgstat_flush_backend(bool nowait, bits32 flags)
299341
if (flags & PGSTAT_BACKEND_FLUSH_WAL)
300342
pgstat_flush_backend_entry_wal(entry_ref);
301343

344+
if (flags & PGSTAT_BACKEND_FLUSH_REL)
345+
pgstat_flush_backend_entry_rel(entry_ref);
346+
302347
pgstat_unlock_entry(entry_ref);
303348

304349
return false;

src/backend/utils/activity/pgstat_relation.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,13 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
898898
dbentry->blocks_fetched += lstats->counts.blocks_fetched;
899899
dbentry->blocks_hit += lstats->counts.blocks_hit;
900900

901+
/* Do the same for backend stats */
902+
if (lstats->relation && lstats->relation->rd_rel->relkind == RELKIND_RELATION)
903+
PendingBackendStats.pending_backendrel.heap_scan += lstats->counts.numscans;
904+
905+
backend_has_relstats = true;
906+
pgstat_report_fixed = true;
907+
901908
return true;
902909
}
903910

src/backend/utils/adt/pgstatfuncs.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,61 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
706706
return (Datum) 0;
707707
}
708708

709+
/*
710+
* Returns statistics of PG backends.
711+
*/
712+
Datum
713+
pg_stat_get_backend_relations(PG_FUNCTION_ARGS)
714+
{
715+
#define PG_STAT_GET_BACKEND_STATS_COLS 3
716+
int num_backends = pgstat_fetch_stat_numbackends();
717+
int curr_backend;
718+
int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
719+
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
720+
721+
InitMaterializedSRF(fcinfo, 0);
722+
723+
/* 1-based index */
724+
for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
725+
{
726+
/* for each row */
727+
Datum values[PG_STAT_GET_BACKEND_STATS_COLS] = {0};
728+
bool nulls[PG_STAT_GET_BACKEND_STATS_COLS] = {0};
729+
LocalPgBackendStatus *local_beentry;
730+
PgBackendStatus *beentry;
731+
PgStat_Backend *backend_stats;
732+
733+
/* Get the next one in the list */
734+
local_beentry = pgstat_get_local_beentry_by_index(curr_backend);
735+
beentry = &local_beentry->backendStatus;
736+
737+
/* If looking for specific PID, ignore all the others */
738+
if (pid != -1 && beentry->st_procpid != pid)
739+
continue;
740+
741+
backend_stats = pgstat_fetch_stat_backend_by_pid(beentry->st_procpid, NULL);
742+
743+
values[0] = Int32GetDatum(beentry->st_procpid);
744+
745+
if (!backend_stats)
746+
continue;
747+
748+
values[1] = Int64GetDatum(backend_stats->heap_scan);
749+
750+
if (backend_stats->stat_reset_timestamp != 0)
751+
values[2] = TimestampTzGetDatum(backend_stats->stat_reset_timestamp);
752+
else
753+
nulls[2] = true;
754+
755+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
756+
757+
/* If only a single backend was requested, and we found it, break. */
758+
if (pid != -1)
759+
break;
760+
}
761+
762+
return (Datum) 0;
763+
}
709764

710765
Datum
711766
pg_backend_pid(PG_FUNCTION_ARGS)

src/include/catalog/pg_proc.dat

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5657,6 +5657,15 @@
56575657
proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
56585658
proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,gss_delegation,leader_pid,query_id}',
56595659
prosrc => 'pg_stat_get_activity' },
5660+
{ oid => '9555',
5661+
descr => 'statistics: statistics about currently active backends',
5662+
proname => 'pg_stat_get_backend_relations', prorows => '100', proisstrict => 'f',
5663+
proretset => 't', provolatile => 's', proparallel => 'r',
5664+
prorettype => 'record', proargtypes => 'int4',
5665+
proallargtypes => '{int4,int4,int8,timestamptz}',
5666+
proargmodes => '{i,o,o,o}',
5667+
proargnames => '{pid,pid,seq_scan,stats_reset}',
5668+
prosrc => 'pg_stat_get_backend_relations' },
56605669
{ oid => '6318', descr => 'describe wait events',
56615670
proname => 'pg_get_wait_events', procost => '10', prorows => '250',
56625671
proretset => 't', provolatile => 'v', prorettype => 'record',

src/include/pgstat.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,8 +495,14 @@ typedef struct PgStat_Backend
495495
TimestampTz stat_reset_timestamp;
496496
PgStat_BktypeIO io_stats;
497497
PgStat_WalCounters wal_counters;
498+
PgStat_Counter heap_scan;
498499
} PgStat_Backend;
499500

501+
typedef struct PgStat_BackendRelPending
502+
{
503+
PgStat_Counter heap_scan;
504+
} PgStat_BackendRelPending;
505+
500506
/* ---------
501507
* PgStat_BackendPending Non-flushed backend stats.
502508
* ---------
@@ -507,6 +513,11 @@ typedef struct PgStat_BackendPending
507513
* Backend statistics store the same amount of IO data as PGSTAT_KIND_IO.
508514
*/
509515
PgStat_PendingIO pending_io;
516+
517+
/*
518+
* Backend statistics related to relations.
519+
*/
520+
PgStat_BackendRelPending pending_backendrel;
510521
} PgStat_BackendPending;
511522

512523
/*
@@ -805,6 +816,12 @@ extern PGDLLIMPORT bool pgstat_track_counts;
805816
extern PGDLLIMPORT int pgstat_track_functions;
806817
extern PGDLLIMPORT int pgstat_fetch_consistency;
807818

819+
/*
820+
* Variables in pgstat_backend.c
821+
*/
822+
823+
extern PGDLLIMPORT PgStat_BackendPending PendingBackendStats;
824+
extern PGDLLIMPORT bool backend_has_relstats;
808825

809826
/*
810827
* Variables in pgstat_bgwriter.c

src/include/utils/pgstat_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,8 @@ extern void pgstat_archiver_snapshot_cb(void);
647647
/* flags for pgstat_flush_backend() */
648648
#define PGSTAT_BACKEND_FLUSH_IO (1 << 0) /* Flush I/O statistics */
649649
#define PGSTAT_BACKEND_FLUSH_WAL (1 << 1) /* Flush WAL statistics */
650-
#define PGSTAT_BACKEND_FLUSH_ALL (PGSTAT_BACKEND_FLUSH_IO | PGSTAT_BACKEND_FLUSH_WAL)
650+
#define PGSTAT_BACKEND_FLUSH_REL (1 << 2) /* Flush relations related statistics */
651+
#define PGSTAT_BACKEND_FLUSH_ALL (PGSTAT_BACKEND_FLUSH_IO | PGSTAT_BACKEND_FLUSH_WAL | PGSTAT_BACKEND_FLUSH_REL)
651652

652653
extern bool pgstat_flush_backend(bool nowait, bits32 flags);
653654
extern bool pgstat_backend_flush_cb(bool nowait);

src/test/regress/expected/rules.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,10 @@ pg_stat_archiver| SELECT archived_count,
18571857
last_failed_time,
18581858
stats_reset
18591859
FROM pg_stat_get_archiver() s(archived_count, last_archived_wal, last_archived_time, failed_count, last_failed_wal, last_failed_time, stats_reset);
1860+
pg_stat_backend_relation| SELECT pid,
1861+
seq_scan,
1862+
stats_reset
1863+
FROM pg_stat_get_backend_relations(NULL::integer) s(pid, seq_scan, stats_reset);
18601864
pg_stat_bgwriter| SELECT pg_stat_get_bgwriter_buf_written_clean() AS buffers_clean,
18611865
pg_stat_get_bgwriter_maxwritten_clean() AS maxwritten_clean,
18621866
pg_stat_get_buf_alloc() AS buffers_alloc,

src/test/regress/expected/stats.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ SELECT t.seq_scan, t.seq_tup_read, t.idx_scan, t.idx_tup_fetch,
118118
pg_catalog.pg_statio_user_tables AS b
119119
WHERE t.relname='tenk2' AND b.relname='tenk2';
120120
COMMIT;
121+
SELECT seq_scan AS seq_scan_before
122+
FROM pg_stat_backend_relation WHERE pid = pg_backend_pid() \gset
121123
-- test effects of TRUNCATE on n_live_tup/n_dead_tup counters
122124
CREATE TABLE trunc_stats_test(id serial);
123125
CREATE TABLE trunc_stats_test1(id serial, stuff text);
@@ -236,6 +238,14 @@ FROM prevstats AS pr;
236238
(1 row)
237239

238240
COMMIT;
241+
SELECT seq_scan AS seq_scan_after
242+
FROM pg_stat_backend_relation WHERE pid = pg_backend_pid() \gset
243+
SELECT :seq_scan_after > :seq_scan_before;
244+
?column?
245+
----------
246+
t
247+
(1 row)
248+
239249
----
240250
-- Basic tests for track_functions
241251
---

0 commit comments

Comments
 (0)