* ExecHashTableExplainEnd * Called before ExecutorEnd to finish EXPLAIN ANALYZE reporting. */
| 2576 | * Called before ExecutorEnd to finish EXPLAIN ANALYZE reporting. |
| 2577 | */ |
| 2578 | static void |
| 2579 | ExecHashTableExplainEnd(PlanState *planstate, struct StringInfoData *buf) |
| 2580 | { |
| 2581 | HashJoinState *hjstate = (HashJoinState *)planstate; |
| 2582 | HashJoinTable hashtable = hjstate->hj_HashTable; |
| 2583 | HashJoinTableStats *stats; |
| 2584 | Instrumentation *jinstrument = hjstate->js.ps.instrument; |
| 2585 | int total_buckets; |
| 2586 | int i; |
| 2587 | |
| 2588 | if (!hashtable || |
| 2589 | !hashtable->stats || |
| 2590 | hashtable->nbatch < 1 || |
| 2591 | !jinstrument || |
| 2592 | !jinstrument->need_cdb) |
| 2593 | return; |
| 2594 | |
| 2595 | stats = hashtable->stats; |
| 2596 | |
| 2597 | Assert(stats->batchstats); |
| 2598 | |
| 2599 | if (!hashtable->eagerlyReleased) |
| 2600 | { |
| 2601 | HashState *hashState = (HashState *) innerPlanState(hjstate); |
| 2602 | |
| 2603 | /* Report on batch in progress, in case the join is being ended early. */ |
| 2604 | ExecHashTableExplainBatchEnd(hashState, hashtable); |
| 2605 | } |
| 2606 | |
| 2607 | /* Report actual work_mem high water mark. */ |
| 2608 | jinstrument->workmemused = Max(jinstrument->workmemused, stats->workmem_max); |
| 2609 | |
| 2610 | /* How much work_mem would suffice to hold all inner tuples in memory? */ |
| 2611 | if (hashtable->nbatch > 1) |
| 2612 | { |
| 2613 | uint64 workmemwanted = 0; |
| 2614 | |
| 2615 | /* Space actually taken by hash rows in completed batches... */ |
| 2616 | for (i = 0; i <= stats->endedbatch; i++) |
| 2617 | workmemwanted += stats->batchstats[i].hashspace_final; |
| 2618 | |
| 2619 | /* ... plus workfile size for original batches not reached, plus... */ |
| 2620 | for (; i < hashtable->nbatch_original; i++) |
| 2621 | workmemwanted += stats->batchstats[i].innerfilesize; |
| 2622 | |
| 2623 | /* ... rows spilled to unreached oflo batches, in case quitting early */ |
| 2624 | for (; i < stats->nbatchstats; i++) |
| 2625 | workmemwanted += stats->batchstats[i].spillspace_in; |
| 2626 | |
| 2627 | /* |
| 2628 | * Sometimes workfiles are used even though all the data would fit |
| 2629 | * in work_mem. For example, if the planner overestimated the inner |
| 2630 | * rel size, it might have instructed us to use more initial batches |
| 2631 | * than were actually needed, causing unnecessary workfile I/O. To |
| 2632 | * avoid this I/O, the user would have to increase work_mem based on |
| 2633 | * the planner's estimate rather than our runtime observations. For |
| 2634 | * now, we don't try to second-guess the planner; just keep quiet. |
| 2635 | */ |
nothing calls this directly
no test coverage detected