From 17f8ffa1e331cd0d95a3c4ccec66ea83d8b893c5 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 18 Mar 2017 17:49:06 -0400 Subject: [PATCH] Fix REFRESH MATERIALIZED VIEW to report activity to the stats collector. The non-concurrent code path for REFRESH MATERIALIZED VIEW failed to report its updates to the stats collector. This is bad since it means auto-analyze doesn't know there's any work to be done. Adjust it to report the refresh as a table truncate followed by insertion of an appropriate number of rows. Since a matview could contain more than INT_MAX rows, change the signature of pgstat_count_heap_insert() to accept an int64 rowcount. (The accumulator it's adding into is already int64, but existing callers could not insert more than a small number of rows at once, so the argument had been declared just "int n".) This is surely a bug fix, but changing pgstat_count_heap_insert()'s API seems too risky for the back branches. Given the lack of previous complaints, I'm not sure it's a big enough problem to justify a kluge solution that would avoid that. So, no back-patch, at least for now. Jim Mlodgenski, adjusted a bit by me Discussion: https://postgr.es/m/CAB_5SRchSz7-WmdO5szdiknG8Oj_GGqJytrk1KRd11yhcMs1KQ@mail.gmail.com --- src/backend/commands/matview.c | 30 +++++++++++++++++++++++++++--- src/backend/postmaster/pgstat.c | 2 +- src/include/pgstat.h | 2 +- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c index a18c917336..c952dea6ea 100644 --- a/src/backend/commands/matview.c +++ b/src/backend/commands/matview.c @@ -30,6 +30,7 @@ #include "executor/spi.h" #include "miscadmin.h" #include "parser/parse_relation.h" +#include "pgstat.h" #include "rewrite/rewriteHandler.h" #include "storage/lmgr.h" #include "storage/smgr.h" @@ -59,7 +60,7 @@ static void transientrel_startup(DestReceiver *self, int operation, TupleDesc ty static bool transientrel_receive(TupleTableSlot *slot, DestReceiver *self); static void transientrel_shutdown(DestReceiver *self); static void transientrel_destroy(DestReceiver *self); -static void refresh_matview_datafill(DestReceiver *dest, Query *query, +static uint64 refresh_matview_datafill(DestReceiver *dest, Query *query, const char *queryString); static char *make_temptable_name_n(char *tempname, int n); @@ -145,6 +146,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, Oid relowner; Oid OIDNewHeap; DestReceiver *dest; + uint64 processed = 0; bool concurrent; LOCKMODE lockmode; char relpersistence; @@ -322,7 +324,7 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, /* Generate the data, if wanted. */ if (!stmt->skipData) - refresh_matview_datafill(dest, dataQuery, queryString); + processed = refresh_matview_datafill(dest, dataQuery, queryString); heap_close(matviewRel, NoLock); @@ -345,8 +347,20 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, Assert(matview_maintenance_depth == old_depth); } else + { refresh_by_heap_swap(matviewOid, OIDNewHeap, relpersistence); + /* + * Inform stats collector about our activity: basically, we truncated + * the matview and inserted some new data. (The concurrent code path + * above doesn't need to worry about this because the inserts and + * deletes it issues get counted by lower-level code.) + */ + pgstat_count_truncate(matviewRel); + if (!stmt->skipData) + pgstat_count_heap_insert(matviewRel, processed); + } + /* Roll back any GUC changes */ AtEOXact_GUC(false, save_nestlevel); @@ -360,8 +374,13 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, /* * refresh_matview_datafill + * + * Execute the given query, sending result rows to "dest" (which will + * insert them into the target matview). + * + * Returns number of rows inserted. */ -static void +static uint64 refresh_matview_datafill(DestReceiver *dest, Query *query, const char *queryString) { @@ -369,6 +388,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query, PlannedStmt *plan; QueryDesc *queryDesc; Query *copied_query; + uint64 processed; /* Lock and rewrite, using a copy to preserve the original query. */ copied_query = copyObject(query); @@ -406,6 +426,8 @@ refresh_matview_datafill(DestReceiver *dest, Query *query, /* run the plan */ ExecutorRun(queryDesc, ForwardScanDirection, 0L); + processed = queryDesc->estate->es_processed; + /* and clean up */ ExecutorFinish(queryDesc); ExecutorEnd(queryDesc); @@ -413,6 +435,8 @@ refresh_matview_datafill(DestReceiver *dest, Query *query, FreeQueryDesc(queryDesc); PopActiveSnapshot(); + + return processed; } DestReceiver * diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 5fe9f35199..3a50488db3 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -1803,7 +1803,7 @@ add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level) * pgstat_count_heap_insert - count a tuple insertion of n tuples */ void -pgstat_count_heap_insert(Relation rel, int n) +pgstat_count_heap_insert(Relation rel, PgStat_Counter n) { PgStat_TableStatus *pgstat_info = rel->pgstat_info; diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 9d2e1fe19f..f2daf32e1a 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -1256,7 +1256,7 @@ pgstat_report_wait_end(void) #define pgstat_count_buffer_write_time(n) \ (pgStatBlockWriteTime += (n)) -extern void pgstat_count_heap_insert(Relation rel, int n); +extern void pgstat_count_heap_insert(Relation rel, PgStat_Counter n); extern void pgstat_count_heap_update(Relation rel, bool hot); extern void pgstat_count_heap_delete(Relation rel); extern void pgstat_count_truncate(Relation rel);