diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/commands/explain.c | 37 | ||||
| -rw-r--r-- | src/backend/utils/sort/tuplestore.c | 53 |
2 files changed, 90 insertions, 0 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 30de9de9d4f..1b5ab503898 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -125,6 +125,7 @@ static void show_sort_info(SortState *sortstate, ExplainState *es); static void show_incremental_sort_info(IncrementalSortState *incrsortstate, ExplainState *es); static void show_hash_info(HashState *hashstate, ExplainState *es); +static void show_material_info(MaterialState *mstate, ExplainState *es); static void show_memoize_info(MemoizeState *mstate, List *ancestors, ExplainState *es); static void show_hashagg_info(AggState *aggstate, ExplainState *es); @@ -2251,6 +2252,9 @@ ExplainNode(PlanState *planstate, List *ancestors, case T_Hash: show_hash_info(castNode(HashState, planstate), es); break; + case T_Material: + show_material_info(castNode(MaterialState, planstate), es); + break; case T_Memoize: show_memoize_info(castNode(MemoizeState, planstate), ancestors, es); @@ -3323,6 +3327,39 @@ show_hash_info(HashState *hashstate, ExplainState *es) } /* + * Show information on material node, storage method and maximum memory/disk + * space used. + */ +static void +show_material_info(MaterialState *mstate, ExplainState *es) +{ + Tuplestorestate *tupstore; + const char *storageType; + int64 spaceUsedKB; + + if (!es->analyze) + return; + + tupstore = mstate->tuplestorestate; + storageType = tuplestore_storage_type_name(tupstore); + spaceUsedKB = BYTES_TO_KILOBYTES(tuplestore_space_used(tupstore)); + + if (es->format != EXPLAIN_FORMAT_TEXT) + { + ExplainPropertyText("Storage", storageType, es); + ExplainPropertyInteger("Maximum Storage", "kB", spaceUsedKB, es); + } + else + { + ExplainIndentText(es); + appendStringInfo(es->str, + "Storage: %s Maximum Storage: " INT64_FORMAT "kB\n", + storageType, + spaceUsedKB); + } +} + +/* * Show information on memoize hits/misses/evictions and memory usage. */ static void diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c index 947a868e569..24bb49ca874 100644 --- a/src/backend/utils/sort/tuplestore.c +++ b/src/backend/utils/sort/tuplestore.c @@ -109,6 +109,7 @@ struct Tuplestorestate bool truncated; /* tuplestore_trim has removed tuples? */ int64 availMem; /* remaining memory available, in bytes */ int64 allowedMem; /* total memory allowed, in bytes */ + int64 maxSpace; /* maximum space used in memory */ int64 tuples; /* number of tuples added */ BufFile *myfile; /* underlying file, or NULL if none */ MemoryContext context; /* memory context for holding tuples */ @@ -238,6 +239,7 @@ static Tuplestorestate *tuplestore_begin_common(int eflags, int maxKBytes); static void tuplestore_puttuple_common(Tuplestorestate *state, void *tuple); static void dumptuples(Tuplestorestate *state); +static void tuplestore_updatemax(Tuplestorestate *state); static unsigned int getlen(Tuplestorestate *state, bool eofOK); static void *copytup_heap(Tuplestorestate *state, void *tup); static void writetup_heap(Tuplestorestate *state, void *tup); @@ -262,6 +264,7 @@ tuplestore_begin_common(int eflags, bool interXact, int maxKBytes) state->truncated = false; state->allowedMem = maxKBytes * 1024L; state->availMem = state->allowedMem; + state->maxSpace = 0; state->myfile = NULL; state->context = CurrentMemoryContext; state->resowner = CurrentResourceOwner; @@ -420,6 +423,9 @@ tuplestore_clear(Tuplestorestate *state) int i; TSReadPointer *readptr; + /* update the maxSpace before doing any USEMEM/FREEMEM adjustments */ + tuplestore_updatemax(state); + if (state->myfile) BufFileClose(state->myfile); state->myfile = NULL; @@ -1402,6 +1408,9 @@ tuplestore_trim(Tuplestorestate *state) Assert(nremove >= state->memtupdeleted); Assert(nremove <= state->memtupcount); + /* before freeing any memory, update maxSpace */ + tuplestore_updatemax(state); + /* Release no-longer-needed tuples */ for (i = state->memtupdeleted; i < nremove; i++) { @@ -1445,6 +1454,49 @@ tuplestore_trim(Tuplestorestate *state) } /* + * tuplestore_updatemax + * Update maxSpace field + */ +static void +tuplestore_updatemax(Tuplestorestate *state) +{ + if (state->status == TSS_INMEM) + state->maxSpace = Max(state->maxSpace, + state->allowedMem - state->availMem); +} + +/* + * tuplestore_storage_type_name + * Return a string description of the storage method used to store the + * tuples. + */ +const char * +tuplestore_storage_type_name(Tuplestorestate *state) +{ + if (state->status == TSS_INMEM) + return "Memory"; + else + return "Disk"; +} + +/* + * tuplestore_space_used + * Return the maximum space used in memory unless the tuplestore has spilled + * to disk, in which case, return the disk space used. + */ +int64 +tuplestore_space_used(Tuplestorestate *state) +{ + /* First, update the maxSpace field */ + tuplestore_updatemax(state); + + if (state->status == TSS_INMEM) + return state->maxSpace; + else + return BufFileSize(state->myfile); +} + +/* * tuplestore_in_memory * * Returns true if the tuplestore has not spilled to disk. @@ -1513,6 +1565,7 @@ writetup_heap(Tuplestorestate *state, void *tup) if (state->backward) /* need trailing length word? */ BufFileWrite(state->myfile, &tuplen, sizeof(tuplen)); + /* no need to call tuplestore_updatemax() when not in TSS_INMEM */ FREEMEM(state, GetMemoryChunkSpace(tuple)); heap_free_minimal_tuple(tuple); } |
