]> granicus.if.org Git - postgresql/commitdiff
Try again to fix accumulation of parallel worker instrumentation.
authorRobert Haas <rhaas@postgresql.org>
Tue, 19 Dec 2017 17:21:56 +0000 (12:21 -0500)
committerRobert Haas <rhaas@postgresql.org>
Tue, 19 Dec 2017 17:44:21 +0000 (12:44 -0500)
When a Gather or Gather Merge node is started and stopped multiple
times, accumulate instrumentation data only once, at the end, instead
of after each execution, to avoid recording inflated totals.

Commit 778e78ae9fa51e58f41cbdc72b293291d02d8984, the previous attempt
at a fix, instead reset the state after every execution, which worked
for the general instrumentation data but had problems for the additional
instrumentation specific to Sort and Hash nodes.

Report by hubert depesz lubaczewski.  Analysis and fix by Amit Kapila,
following a design proposal from Thomas Munro, with a comment tweak
by me.

Discussion: http://postgr.es/m/20171127175631.GA405@depesz.com

src/backend/executor/execParallel.c
src/test/regress/expected/select_parallel.out
src/test/regress/sql/select_parallel.sql

index 989cf5b80b1aabecf738d1fb67d90ead128aa4af..609643dcf94d312fbecea32d32480532430d433a 100644 (file)
@@ -723,7 +723,7 @@ ExecParallelRetrieveInstrumentation(PlanState *planstate,
 
 /*
  * Finish parallel execution.  We wait for parallel workers to finish, and
- * accumulate their buffer usage and instrumentation.
+ * accumulate their buffer usage.
  */
 void
 ExecParallelFinish(ParallelExecutorInfo *pei)
@@ -769,23 +769,23 @@ ExecParallelFinish(ParallelExecutorInfo *pei)
        for (i = 0; i < nworkers; i++)
                InstrAccumParallelQuery(&pei->buffer_usage[i]);
 
-       /* Finally, accumulate instrumentation, if any. */
-       if (pei->instrumentation)
-               ExecParallelRetrieveInstrumentation(pei->planstate,
-                                                                                       pei->instrumentation);
-
        pei->finished = true;
 }
 
 /*
- * Clean up whatever ParallelExecutorInfo resources still exist after
- * ExecParallelFinish.  We separate these routines because someone might
- * want to examine the contents of the DSM after ExecParallelFinish and
- * before calling this routine.
+ * Accumulate instrumentation, and then clean up whatever ParallelExecutorInfo
+ * resources still exist after ExecParallelFinish.  We separate these
+ * routines because someone might want to examine the contents of the DSM
+ * after ExecParallelFinish and before calling this routine.
  */
 void
 ExecParallelCleanup(ParallelExecutorInfo *pei)
 {
+       /* Accumulate instrumentation, if any. */
+       if (pei->instrumentation)
+               ExecParallelRetrieveInstrumentation(pei->planstate,
+                                                                                       pei->instrumentation);
+
        if (pei->area != NULL)
        {
                dsa_detach(pei->area);
index ecabd35cca6573cecc08192f350c65b5296ce0f5..07b7994c5bd6ec7230a2b1784188615bcf9e79f6 100644 (file)
@@ -300,7 +300,28 @@ select count(*) from bmscantest where a>1;
  99999
 (1 row)
 
+-- test accumulation of stats for parallel nodes
 reset enable_seqscan;
+alter table tenk2 set (parallel_workers = 0);
+explain (analyze, timing off, summary off, costs off)
+   select count(*) from tenk1, tenk2 where tenk1.hundred > 1
+        and tenk2.thousand=0;
+                                QUERY PLAN                                
+--------------------------------------------------------------------------
+ Aggregate (actual rows=1 loops=1)
+   ->  Nested Loop (actual rows=98000 loops=1)
+         ->  Seq Scan on tenk2 (actual rows=10 loops=1)
+               Filter: (thousand = 0)
+               Rows Removed by Filter: 9990
+         ->  Gather (actual rows=9800 loops=10)
+               Workers Planned: 4
+               Workers Launched: 4
+               ->  Parallel Seq Scan on tenk1 (actual rows=1960 loops=50)
+                     Filter: (hundred > 1)
+                     Rows Removed by Filter: 40
+(11 rows)
+
+alter table tenk2 reset (parallel_workers);
 reset enable_indexscan;
 reset enable_hashjoin;
 reset enable_mergejoin;
index 280c78765362bd44cdba3daf33ca47823a1764ea..61c41d0765058642bdfead898fae2990fee41996 100644 (file)
@@ -116,7 +116,14 @@ insert into bmscantest select r, 'fooooooooooooooooooooooooooooooooooooooooooooo
 create index i_bmtest ON bmscantest(a);
 select count(*) from bmscantest where a>1;
 
+-- test accumulation of stats for parallel nodes
 reset enable_seqscan;
+alter table tenk2 set (parallel_workers = 0);
+explain (analyze, timing off, summary off, costs off)
+   select count(*) from tenk1, tenk2 where tenk1.hundred > 1
+        and tenk2.thousand=0;
+alter table tenk2 reset (parallel_workers);
+
 reset enable_indexscan;
 reset enable_hashjoin;
 reset enable_mergejoin;