]> granicus.if.org Git - postgresql/commitdiff
Fix REFRESH MATERIALIZED VIEW to report activity to the stats collector.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 18 Mar 2017 21:49:06 +0000 (17:49 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 18 Mar 2017 21:49:39 +0000 (17:49 -0400)
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
src/backend/postmaster/pgstat.c
src/include/pgstat.h

index a18c9173360d5adf322d82102ba8b27f64b118f1..c952dea6ead81ca6986d340072253932d6a35900 100644 (file)
@@ -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 *
index 5fe9f35199ae8296dd8d425f3e5327d2841e7dbe..3a50488db3286036583d9fed2d18ea956cad4cdd 100644 (file)
@@ -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;
 
index 9d2e1fe19f43b6f95237a605011d26c12153c100..f2daf32e1abaa868cd9d7cec18fdfc1f14efe8b7 100644 (file)
@@ -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);