aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/explain.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r--src/backend/commands/explain.c79
1 files changed, 52 insertions, 27 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 7e4fbafc535..2156385ac88 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -2379,62 +2379,87 @@ show_sort_info(SortState *sortstate, ExplainState *es)
static void
show_hash_info(HashState *hashstate, ExplainState *es)
{
- HashInstrumentation *hinstrument = NULL;
+ HashInstrumentation hinstrument = {0};
/*
* In a parallel query, the leader process may or may not have run the
* hash join, and even if it did it may not have built a hash table due to
* timing (if it started late it might have seen no tuples in the outer
* relation and skipped building the hash table). Therefore we have to be
- * prepared to get instrumentation data from a worker if there is no hash
- * table.
+ * prepared to get instrumentation data from all participants.
*/
if (hashstate->hashtable)
- {
- hinstrument = (HashInstrumentation *)
- palloc(sizeof(HashInstrumentation));
- ExecHashGetInstrumentation(hinstrument, hashstate->hashtable);
- }
- else if (hashstate->shared_info)
+ ExecHashGetInstrumentation(&hinstrument, hashstate->hashtable);
+
+ /*
+ * Merge results from workers. In the parallel-oblivious case, the
+ * results from all participants should be identical, except where
+ * participants didn't run the join at all so have no data. In the
+ * parallel-aware case, we need to consider all the results. Each worker
+ * may have seen a different subset of batches and we want to find the
+ * highest memory usage for any one batch across all batches.
+ */
+ if (hashstate->shared_info)
{
SharedHashInfo *shared_info = hashstate->shared_info;
- int i;
+ int i;
- /* Find the first worker that built a hash table. */
for (i = 0; i < shared_info->num_workers; ++i)
{
- if (shared_info->hinstrument[i].nbatch > 0)
+ HashInstrumentation *worker_hi = &shared_info->hinstrument[i];
+
+ if (worker_hi->nbatch > 0)
{
- hinstrument = &shared_info->hinstrument[i];
- break;
+ /*
+ * Every participant should agree on the buckets, so to be
+ * sure we have a value we'll just overwrite each time.
+ */
+ hinstrument.nbuckets = worker_hi->nbuckets;
+ hinstrument.nbuckets_original = worker_hi->nbuckets_original;
+
+ /*
+ * Normally every participant should agree on the number of
+ * batches too, but it's possible for a backend that started
+ * late and missed the whole join not to have the final nbatch
+ * number. So we'll take the largest number.
+ */
+ hinstrument.nbatch = Max(hinstrument.nbatch, worker_hi->nbatch);
+ hinstrument.nbatch_original = worker_hi->nbatch_original;
+
+ /*
+ * In a parallel-aware hash join, for now we report the
+ * maximum peak memory reported by any worker.
+ */
+ hinstrument.space_peak =
+ Max(hinstrument.space_peak, worker_hi->space_peak);
}
}
}
- if (hinstrument)
+ if (hinstrument.nbatch > 0)
{
- long spacePeakKb = (hinstrument->space_peak + 1023) / 1024;
+ long spacePeakKb = (hinstrument.space_peak + 1023) / 1024;
if (es->format != EXPLAIN_FORMAT_TEXT)
{
- ExplainPropertyLong("Hash Buckets", hinstrument->nbuckets, es);
+ ExplainPropertyLong("Hash Buckets", hinstrument.nbuckets, es);
ExplainPropertyLong("Original Hash Buckets",
- hinstrument->nbuckets_original, es);
- ExplainPropertyLong("Hash Batches", hinstrument->nbatch, es);
+ hinstrument.nbuckets_original, es);
+ ExplainPropertyLong("Hash Batches", hinstrument.nbatch, es);
ExplainPropertyLong("Original Hash Batches",
- hinstrument->nbatch_original, es);
+ hinstrument.nbatch_original, es);
ExplainPropertyLong("Peak Memory Usage", spacePeakKb, es);
}
- else if (hinstrument->nbatch_original != hinstrument->nbatch ||
- hinstrument->nbuckets_original != hinstrument->nbuckets)
+ else if (hinstrument.nbatch_original != hinstrument.nbatch ||
+ hinstrument.nbuckets_original != hinstrument.nbuckets)
{
appendStringInfoSpaces(es->str, es->indent * 2);
appendStringInfo(es->str,
"Buckets: %d (originally %d) Batches: %d (originally %d) Memory Usage: %ldkB\n",
- hinstrument->nbuckets,
- hinstrument->nbuckets_original,
- hinstrument->nbatch,
- hinstrument->nbatch_original,
+ hinstrument.nbuckets,
+ hinstrument.nbuckets_original,
+ hinstrument.nbatch,
+ hinstrument.nbatch_original,
spacePeakKb);
}
else
@@ -2442,7 +2467,7 @@ show_hash_info(HashState *hashstate, ExplainState *es)
appendStringInfoSpaces(es->str, es->indent * 2);
appendStringInfo(es->str,
"Buckets: %d Batches: %d Memory Usage: %ldkB\n",
- hinstrument->nbuckets, hinstrument->nbatch,
+ hinstrument.nbuckets, hinstrument.nbatch,
spacePeakKb);
}
}