11diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
2- index 92969636b7..42446d4e93 100644
2+ index 92969636b7..d05b07e037 100644
33--- a/src/backend/commands/explain.c
44+++ b/src/backend/commands/explain.c
5- @@ -46,6 +46,9 @@ ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL;
5+ @@ -24,6 +24,7 @@
6+ #include "nodes/extensible.h"
7+ #include "nodes/makefuncs.h"
8+ #include "nodes/nodeFuncs.h"
9+ + #include "optimizer/cost.h"
10+ #include "parser/parsetree.h"
11+ #include "rewrite/rewriteHandler.h"
12+ #include "storage/bufmgr.h"
13+ @@ -46,6 +47,9 @@ ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL;
614 /* Hook for plugins to get control in explain_get_index_name() */
715 explain_get_index_name_hook_type explain_get_index_name_hook = NULL;
816
@@ -12,7 +20,7 @@ index 92969636b7..42446d4e93 100644
1220
1321 /* OR-able flags for ExplainXMLTag() */
1422 #define X_OPENING 0
15- @@ -596,6 +599 ,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
23+ @@ -596,6 +600 ,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
1624 ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
1725 es);
1826
@@ -22,45 +30,41 @@ index 92969636b7..42446d4e93 100644
2230+
2331 ExplainCloseGroup("Query", NULL, true, es);
2432 }
25-
26- @@ -1041,6 +1048,17 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
27- return planstate_tree_walker(planstate, ExplainPreScanNode, rels_used);
28- }
29-
30- + static bool
31- + we_need_to_sum_tuples(const Plan *plan)
32- + {
33- + if (plan->path_parallel_workers > 0 && (
34- + plan->parallel_aware || nodeTag(plan) == T_HashJoin ||
35- + nodeTag(plan) == T_MergeJoin ||
36- + nodeTag(plan) == T_NestLoop))
37- + return true;
38- + return false;
39- + }
40- +
41- /*
42- * ExplainNode -
43- * Appends a description of a plan tree to es->str
44- @@ -1523,6 +1541,24 @@ ExplainNode(PlanState *planstate, List *ancestors,
33+
34+ @@ -1523,6 +1531,38 @@ ExplainNode(PlanState *planstate, List *ancestors,
4535 appendStringInfo(es->str,
4636 " (actual rows=%.0f loops=%.0f)",
4737 rows, nloops);
38+ +
4839+ #ifdef AQO_EXPLAIN
49- + if (es->verbose && plan)
40+ + if (es->verbose && plan && planstate->instrument )
5041+ {
5142+ int wrkrs = 1;
5243+ double error = -1.;
5344+
54- + if (planstate->worker_instrument && we_need_to_sum_tuples(plan))
55- + wrkrs += planstate->worker_instrument->num_workers;
45+ + if (planstate->worker_instrument && IsParallelTuplesProcessing(plan))
46+ + {
47+ + int i;
48+ + for (i = 0; i < planstate->worker_instrument->num_workers; i++)
49+ + {
50+ + Instrumentation *instrument = &planstate->worker_instrument->instrument[i];
51+ + if (instrument->nloops <= 0)
52+ + continue;
53+ + wrkrs++;
54+ + }
55+ + }
5656+
5757+ if (plan->predicted_cardinality > 0.)
5858+ {
59- + error = 100. * (plan->predicted_cardinality-(rows*wrkrs)) / (rows * wrkrs);
59+ + error = 100. * (plan->predicted_cardinality - (rows*wrkrs))
60+ + / plan->predicted_cardinality;
6061+ appendStringInfo(es->str,
61- + " (AQO predicted: cardinality=%.0lf , error=%.0lf%%,fss =%d)",
62+ + " (AQO predicted: cardinality=%lf , error=%.0lf%%,fsspace_hash =%d)",
6263+ plan->predicted_cardinality, error, plan->fss_hash);
6364+ }
65+ + else
66+ + appendStringInfo(es->str, " (AQO not used, fsspace_hash=%d)",
67+ + plan->fss_hash);
6468+ }
6569+ #endif
6670 }
@@ -84,7 +88,7 @@ index 78deade89b..b1470147e9 100644
8488 COPY_BITMAPSET_FIELD(allParam);
8589 }
8690diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
87- index a2a9b1f7be..bc7a69bb05 100644
91+ index a2a9b1f7be..4b766b9885 100644
8892--- a/src/backend/optimizer/path/costsize.c
8993+++ b/src/backend/optimizer/path/costsize.c
9094@@ -96,6 +96,10 @@
@@ -401,7 +405,22 @@ index a2a9b1f7be..bc7a69bb05 100644
401405 {
402406 doublenrows;
403407
404- @@ -5478,10 +5594,10 @@ page_size(double tuples, int width)
408+ @@ -5474,14 +5590,25 @@ page_size(double tuples, int width)
409+ return ceil(relation_byte_size(tuples, width) / BLCKSZ);
410+ }
411+
412+ + bool
413+ + IsParallelTuplesProcessing(const Plan *plan)
414+ + {
415+ + if (plan->path_parallel_workers > 0 && (
416+ + plan->parallel_aware || nodeTag(plan) == T_HashJoin ||
417+ + nodeTag(plan) == T_MergeJoin ||
418+ + nodeTag(plan) == T_NestLoop))
419+ + return true;
420+ + return false;
421+ + }
422+ +
423+ /*
405424 * Estimate the fraction of the work that each worker will do given the
406425 * number of workers budgeted for the path.
407426 */
@@ -415,7 +434,7 @@ index a2a9b1f7be..bc7a69bb05 100644
415434
416435 /*
417436 * Early experience with parallel query suggests that when there is only
418- @@ -5498,7 +5614 ,7 @@ get_parallel_divisor(Path *path)
437+ @@ -5498,7 +5625 ,7 @@ get_parallel_divisor(Path *path)
419438 {
420439 doubleleader_contribution;
421440
@@ -927,7 +946,7 @@ index 70f8b8e22b..d188c2596a 100644
927946 * Information for management of parameter-change-driven rescanning
928947 *
929948diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
930- index 9b6bdbc518..4f93e222ca 100644
949+ index 9b6bdbc518..2a0caa6474 100644
931950--- a/src/include/optimizer/cost.h
932951+++ b/src/include/optimizer/cost.h
933952@@ -39,6 +39,33 @@ typedef enum
@@ -998,10 +1017,11 @@ index 9b6bdbc518..4f93e222ca 100644
9981017 extern void set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel);
9991018 extern void set_function_size_estimates(PlannerInfo *root, RelOptInfo *rel);
10001019 extern void set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel);
1001- @@ -198,5 +241,6 @@ extern void set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel);
1020+ @@ -198,5 +241,7 @@ extern void set_foreign_size_estimates(PlannerInfo *root, RelOptInfo *rel);
10021021 extern PathTarget *set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target);
10031022 extern double compute_bitmap_pages(PlannerInfo *root, RelOptInfo *baserel,
10041023 Path *bitmapqual, int loop_count, Cost *cost, double *tuple);
1024+ + extern bool IsParallelTuplesProcessing(const Plan *plan);
10051025+ extern double get_parallel_divisor(int parallel_workers);
10061026
10071027 #endif/* COST_H */