diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-04-11 12:39:19 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-04-11 12:39:19 -0400 |
commit | 969f9d0b4ba574bb8df65683dbf7a09c030f3e67 (patch) | |
tree | fff0c61c0079b85371dd30bf9f30fa15bc8f1355 /src/backend/commands/explain.c | |
parent | 5c27bce7f39ded1f027475221b732bbbc31a2bfe (diff) | |
download | postgresql-969f9d0b4ba574bb8df65683dbf7a09c030f3e67.tar.gz postgresql-969f9d0b4ba574bb8df65683dbf7a09c030f3e67.zip |
Make EXPLAIN report maximum hashtable usage across multiple rescans.
Before discarding the old hash table in ExecReScanHashJoin, capture
its statistics, ensuring that we report the maximum hashtable size
across repeated rescans of the hash input relation. We can repurpose
the existing code for reporting hashtable size in parallel workers
to help with this, making the patch pretty small. This also ensures
that if rescans happen within parallel workers, we get the correct
maximums across all instances.
Konstantin Knizhnik and Tom Lane, per diagnosis by Thomas Munro
of a trouble report from Alvaro Herrera.
Discussion: https://postgr.es/m/20200323165059.GA24950@alvherre.pgsql
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r-- | src/backend/commands/explain.c | 46 |
1 files changed, 17 insertions, 29 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 455f54ef83f..f3c8da1e01b 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -2964,22 +2964,25 @@ show_hash_info(HashState *hashstate, ExplainState *es) HashInstrumentation hinstrument = {0}; /* + * Collect stats from the local process, even when it's a parallel query. * 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 all participants. */ - if (hashstate->hashtable) - ExecHashGetInstrumentation(&hinstrument, hashstate->hashtable); + if (hashstate->hinstrument) + memcpy(&hinstrument, hashstate->hinstrument, + sizeof(HashInstrumentation)); /* * 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. + * may have seen a different subset of batches and we want to report the + * highest memory usage across all batches. We take the maxima of other + * values too, for the same reasons as in ExecHashAccumInstrumentation. */ if (hashstate->shared_info) { @@ -2990,31 +2993,16 @@ show_hash_info(HashState *hashstate, ExplainState *es) { HashInstrumentation *worker_hi = &shared_info->hinstrument[i]; - if (worker_hi->nbatch > 0) - { - /* - * 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); - } + hinstrument.nbuckets = Max(hinstrument.nbuckets, + worker_hi->nbuckets); + hinstrument.nbuckets_original = Max(hinstrument.nbuckets_original, + worker_hi->nbuckets_original); + hinstrument.nbatch = Max(hinstrument.nbatch, + worker_hi->nbatch); + hinstrument.nbatch_original = Max(hinstrument.nbatch_original, + worker_hi->nbatch_original); + hinstrument.space_peak = Max(hinstrument.space_peak, + worker_hi->space_peak); } } |