summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/commands/explain.c37
-rw-r--r--src/backend/utils/sort/tuplestore.c53
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);
}