Hi.

This is a proposal for a new feature in statistics collector.
I think we need to add statistics about refresh matview to pg_stat_all_tables view.

When the "REFRESH MATERIALIZED VIEW" was executed, the number of times it was executed
and date it took were not recorded anywhere.

"pg_stat_statements" can be used to get the number of executions and the date and time of execution,
but this information is statement-based, not view-based.
Also, that method requires the high cost of "pg_stat_statements".

This patch will add statistics(count, last time) about "REFRESH MATERIALIZED VIEW"
to pg_stat_all_tables(pg_stat_user_tables, [pg_stat_sys_tables]).

What do you think?

Regards,
Seino Yuki
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 643e1ad49f..884585af0c 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -4285,6 +4285,26 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
        daemon
       </para></entry>
      </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>last_refresh_matview_time</structfield> <type>timestamp with time zone</type>
+      </para>
+      <para>
+       Last time at which this materialized view was refreshed
+       (If this record is materialized view)
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>refresh_matview_count</structfield> <type>bigint</type>
+      </para>
+      <para>
+       Number of times this materialized view has been refreshed
+       (If this record is materialized view)
+      </para></entry>
+     </row>
     </tbody>
    </tgroup>
   </table>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 999d984068..70375c7e19 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -656,7 +656,9 @@ CREATE VIEW pg_stat_all_tables AS
             pg_stat_get_vacuum_count(C.oid) AS vacuum_count,
             pg_stat_get_autovacuum_count(C.oid) AS autovacuum_count,
             pg_stat_get_analyze_count(C.oid) AS analyze_count,
-            pg_stat_get_autoanalyze_count(C.oid) AS autoanalyze_count
+            pg_stat_get_autoanalyze_count(C.oid) AS autoanalyze_count,
+            pg_stat_get_last_refresh_matview_time(C.oid) AS last_refresh_matview_time,
+            pg_stat_get_refresh_matview_count(C.oid) AS refresh_matview_count
     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/commands/matview.c b/src/backend/commands/matview.c
index 25bbd8a5c1..20733b04de 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -356,6 +356,9 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
 
 	ObjectAddressSet(address, RelationRelationId, matviewOid);
 
+	/* Report results to the stats collector */
+	pgstat_report_refresh_matview(matviewOid);
+
 	/*
 	 * Save the rowcount so that pg_stat_statements can track the total number
 	 * of rows processed by REFRESH MATERIALIZED VIEW command. Note that we
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 11702f2a80..6a378831a9 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -358,6 +358,7 @@ static void pgstat_recv_checksum_failure(PgStat_MsgChecksumFailure *msg, int len
 static void pgstat_recv_connstat(PgStat_MsgConn *msg, int len);
 static void pgstat_recv_replslot(PgStat_MsgReplSlot *msg, int len);
 static void pgstat_recv_tempfile(PgStat_MsgTempFile *msg, int len);
+static void pgstat_recv_refresh_matview(PgStat_MsgRefreshMatview *msg, int len);
 
 /* ------------------------------------------------------------
  * Public functions called from postmaster follow
@@ -1863,6 +1864,28 @@ pgstat_report_replslot_drop(const char *slotname)
 	pgstat_send(&msg, sizeof(PgStat_MsgReplSlot));
 }
 
+/* ---------
+ * pgstat_report_refresh_matview() -
+ *
+ *	Tell the collector about the matview we just refreshed.
+ * ---------
+ */
+void
+pgstat_report_refresh_matview(Oid tableoid)
+{
+	PgStat_MsgRefreshMatview msg;
+
+	if (pgStatSock == PGINVALID_SOCKET || !pgstat_track_counts)
+		return;
+
+	pgstat_setheader(&msg.m_hdr, PGSTAT_MTYPE_REFRESHEDMATVIEW);
+	msg.m_databaseid = MyDatabaseId;
+	msg.m_tableoid = tableoid;
+	msg.refreshmatview_time = GetCurrentTimestamp();
+	pgstat_send(&msg, sizeof(msg));
+}
+
+
 /* ----------
  * pgstat_ping() -
  *
@@ -3424,6 +3447,10 @@ PgstatCollectorMain(int argc, char *argv[])
 					pgstat_recv_connstat(&msg.msg_conn, len);
 					break;
 
+				case PGSTAT_MTYPE_REFRESHEDMATVIEW:
+					pgstat_recv_refresh_matview(&msg.msg_refreshmatview, len);
+					break;
+
 				default:
 					break;
 			}
@@ -3600,6 +3627,8 @@ pgstat_get_tab_entry(PgStat_StatDBEntry *dbentry, Oid tableoid, bool create)
 		result->analyze_count = 0;
 		result->autovac_analyze_timestamp = 0;
 		result->autovac_analyze_count = 0;
+		result->matview_refresh_timestamp = 0;
+		result->matview_refresh_count = 0;
 	}
 
 	return result;
@@ -4883,6 +4912,8 @@ pgstat_recv_tabstat(PgStat_MsgTabstat *msg, int len)
 			tabentry->analyze_count = 0;
 			tabentry->autovac_analyze_timestamp = 0;
 			tabentry->autovac_analyze_count = 0;
+			tabentry->matview_refresh_timestamp = 0;
+			tabentry->matview_refresh_count = 0;
 		}
 		else
 		{
@@ -5650,6 +5681,28 @@ pgstat_recv_funcpurge(PgStat_MsgFuncpurge *msg, int len)
 	}
 }
 
+/* ----------
+ * pgstat_recv_refresh_matview() -
+ *
+ *	Process a REFRESH MATERIALIZED VIEW message.
+ * ----------
+ */
+static void
+pgstat_recv_refresh_matview(PgStat_MsgRefreshMatview *msg, int len)
+{
+	PgStat_StatDBEntry *dbentry;
+	PgStat_StatTabEntry *tabentry;
+
+	/*
+	 * Store the data in the table's hashtable entry.
+	 */
+	dbentry = pgstat_get_db_entry(msg->m_databaseid, true);
+	tabentry = pgstat_get_tab_entry(dbentry, msg->m_tableoid, true);
+	tabentry->matview_refresh_timestamp = msg->refreshmatview_time;
+	tabentry->matview_refresh_count++;
+}
+
+
 /* ----------
  * pgstat_write_statsfile_needed() -
  *
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index f0e09eae4d..cfd7f6715c 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -378,6 +378,39 @@ pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
 	PG_RETURN_INT64(result);
 }
 
+Datum
+pg_stat_get_last_refresh_matview_time(PG_FUNCTION_ARGS)
+{
+	Oid			relid = PG_GETARG_OID(0);
+	TimestampTz result;
+	PgStat_StatTabEntry *tabentry;
+
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
+		result = 0;
+	else
+		result = tabentry->matview_refresh_timestamp;
+
+	if (result == 0)
+		PG_RETURN_NULL();
+	else
+		PG_RETURN_TIMESTAMPTZ(result);
+}
+
+Datum
+pg_stat_get_refresh_matview_count(PG_FUNCTION_ARGS)
+{
+	Oid			relid = PG_GETARG_OID(0);
+	int64		result;
+	PgStat_StatTabEntry *tabentry;
+
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
+		result = 0;
+	else
+		result = (int64) (tabentry->matview_refresh_count);
+
+	PG_RETURN_INT64(result);
+}
+
 Datum
 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
 {
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index fde251fa4f..bdf89a3f52 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -5271,6 +5271,14 @@
   proname => 'pg_stat_get_autoanalyze_count', provolatile => 's',
   proparallel => 'r', prorettype => 'int8', proargtypes => 'oid',
   prosrc => 'pg_stat_get_autoanalyze_count' },
+{ oid => '6205', descr => 'statistics: number of manual vacuums for a table',
+  proname => 'pg_stat_get_last_refresh_matview_time', provolatile => 's', proparallel => 'r',
+  prorettype => 'timestamptz', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_last_refresh_matview_time' },
+{ oid => '6206', descr => 'statistics: number of manual vacuums for a table',
+  proname => 'pg_stat_get_refresh_matview_count', provolatile => 's', proparallel => 'r',
+  prorettype => 'int8', proargtypes => 'oid',
+  prosrc => 'pg_stat_get_refresh_matview_count' },
 { oid => '1936', descr => 'statistics: currently active backend IDs',
   proname => 'pg_stat_get_backend_idset', prorows => '100', proretset => 't',
   provolatile => 's', proparallel => 'r', prorettype => 'int4',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 9612c0a6c2..1c3abce875 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -82,6 +82,7 @@ typedef enum StatMsgType
 	PGSTAT_MTYPE_CHECKSUMFAILURE,
 	PGSTAT_MTYPE_REPLSLOT,
 	PGSTAT_MTYPE_CONNECTION,
+	PGSTAT_MTYPE_REFRESHEDMATVIEW
 } StatMsgType;
 
 /* ----------
@@ -676,6 +677,18 @@ typedef struct PgStat_MsgConn
 	SessionEndType m_disconnect;
 } PgStat_MsgConn;
 
+/* ----------
+ * PgStat_MsgRefreshMatview			Sent by the backend to update statistics.
+									after REFRESH MATERIALIZED VIEW.
+ * ----------
+ */
+typedef struct PgStat_MsgRefreshMatview
+{
+	PgStat_MsgHdr m_hdr;
+	Oid			m_databaseid;
+	Oid			m_tableoid;
+	TimestampTz refreshmatview_time;
+} PgStat_MsgRefreshMatview;
 
 /* ----------
  * PgStat_Msg					Union over all possible messages.
@@ -710,6 +723,7 @@ typedef union PgStat_Msg
 	PgStat_MsgChecksumFailure msg_checksumfailure;
 	PgStat_MsgReplSlot msg_replslot;
 	PgStat_MsgConn msg_conn;
+	PgStat_MsgRefreshMatview msg_refreshmatview;
 } PgStat_Msg;
 
 
@@ -807,6 +821,9 @@ typedef struct PgStat_StatTabEntry
 	PgStat_Counter analyze_count;
 	TimestampTz autovac_analyze_timestamp;	/* autovacuum initiated */
 	PgStat_Counter autovac_analyze_count;
+
+	TimestampTz matview_refresh_timestamp;	/* refresh matview executed */
+	PgStat_Counter matview_refresh_count;
 } PgStat_StatTabEntry;
 
 
@@ -1011,7 +1028,7 @@ extern void pgstat_report_checksum_failure(void);
 extern void pgstat_report_replslot(const PgStat_StatReplSlotEntry *repSlotStat);
 extern void pgstat_report_replslot_create(const char *slotname);
 extern void pgstat_report_replslot_drop(const char *slotname);
-
+extern void pgstat_report_refresh_matview(Oid tableoid);
 extern void pgstat_initialize(void);
 
 
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index e5ab11275d..9471afb267 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1803,7 +1803,9 @@ pg_stat_all_tables| SELECT c.oid AS relid,
     pg_stat_get_vacuum_count(c.oid) AS vacuum_count,
     pg_stat_get_autovacuum_count(c.oid) AS autovacuum_count,
     pg_stat_get_analyze_count(c.oid) AS analyze_count,
-    pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count
+    pg_stat_get_autoanalyze_count(c.oid) AS autoanalyze_count,
+    pg_stat_get_last_refresh_matview_time(c.oid) AS last_refresh_matview_time,
+    pg_stat_get_refresh_matview_count(c.oid) AS refresh_matview_count
    FROM ((pg_class c
      LEFT JOIN pg_index i ON ((c.oid = i.indrelid)))
      LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
@@ -2126,7 +2128,9 @@ pg_stat_sys_tables| SELECT pg_stat_all_tables.relid,
     pg_stat_all_tables.vacuum_count,
     pg_stat_all_tables.autovacuum_count,
     pg_stat_all_tables.analyze_count,
-    pg_stat_all_tables.autoanalyze_count
+    pg_stat_all_tables.autoanalyze_count,
+    pg_stat_all_tables.last_refresh_matview_time,
+    pg_stat_all_tables.refresh_matview_count
    FROM pg_stat_all_tables
   WHERE ((pg_stat_all_tables.schemaname = ANY (ARRAY['pg_catalog'::name, 'information_schema'::name])) OR (pg_stat_all_tables.schemaname ~ '^pg_toast'::text));
 pg_stat_user_functions| SELECT p.oid AS funcid,
@@ -2170,7 +2174,9 @@ pg_stat_user_tables| SELECT pg_stat_all_tables.relid,
     pg_stat_all_tables.vacuum_count,
     pg_stat_all_tables.autovacuum_count,
     pg_stat_all_tables.analyze_count,
-    pg_stat_all_tables.autoanalyze_count
+    pg_stat_all_tables.autoanalyze_count,
+    pg_stat_all_tables.last_refresh_matview_time,
+    pg_stat_all_tables.refresh_matview_count
    FROM pg_stat_all_tables
   WHERE ((pg_stat_all_tables.schemaname <> ALL (ARRAY['pg_catalog'::name, 'information_schema'::name])) AND (pg_stat_all_tables.schemaname !~ '^pg_toast'::text));
 pg_stat_wal| SELECT w.wal_records,

Reply via email to