mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 00:03:09 -04:00
Create memory context for HashAgg with a reasonable maxBlockSize.
If the memory context's maxBlockSize is too big, a single block allocation can suddenly exceed work_mem. For Hash Aggregation, this can mean spilling to disk too early or reporting a confusing memory usage number for EXPLAN ANALYZE. Introduce CreateWorkExprContext(), which is like CreateExprContext(), except that it creates the AllocSet with a maxBlockSize that is reasonable in proportion to work_mem. Right now, CreateWorkExprContext() is only used by Hash Aggregation, but it may be generally useful in the future. Discussion: https://postgr.es/m/412a3fbf306f84d8d78c4009e11791867e62b87c.camel@j-davis.com
This commit is contained in:
parent
f0705bb628
commit
50a38f6517
@ -53,6 +53,7 @@
|
|||||||
#include "executor/executor.h"
|
#include "executor/executor.h"
|
||||||
#include "jit/jit.h"
|
#include "jit/jit.h"
|
||||||
#include "mb/pg_wchar.h"
|
#include "mb/pg_wchar.h"
|
||||||
|
#include "miscadmin.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "partitioning/partdesc.h"
|
#include "partitioning/partdesc.h"
|
||||||
@ -227,21 +228,13 @@ FreeExecutorState(EState *estate)
|
|||||||
MemoryContextDelete(estate->es_query_cxt);
|
MemoryContextDelete(estate->es_query_cxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/*
|
||||||
* CreateExprContext
|
* Internal implementation for CreateExprContext() and CreateWorkExprContext()
|
||||||
*
|
* that allows control over the AllocSet parameters.
|
||||||
* Create a context for expression evaluation within an EState.
|
|
||||||
*
|
|
||||||
* An executor run may require multiple ExprContexts (we usually make one
|
|
||||||
* for each Plan node, and a separate one for per-output-tuple processing
|
|
||||||
* such as constraint checking). Each ExprContext has its own "per-tuple"
|
|
||||||
* memory context.
|
|
||||||
*
|
|
||||||
* Note we make no assumption about the caller's memory context.
|
|
||||||
* ----------------
|
|
||||||
*/
|
*/
|
||||||
ExprContext *
|
static ExprContext *
|
||||||
CreateExprContext(EState *estate)
|
CreateExprContextInternal(EState *estate, Size minContextSize,
|
||||||
|
Size initBlockSize, Size maxBlockSize)
|
||||||
{
|
{
|
||||||
ExprContext *econtext;
|
ExprContext *econtext;
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
@ -264,7 +257,9 @@ CreateExprContext(EState *estate)
|
|||||||
econtext->ecxt_per_tuple_memory =
|
econtext->ecxt_per_tuple_memory =
|
||||||
AllocSetContextCreate(estate->es_query_cxt,
|
AllocSetContextCreate(estate->es_query_cxt,
|
||||||
"ExprContext",
|
"ExprContext",
|
||||||
ALLOCSET_DEFAULT_SIZES);
|
minContextSize,
|
||||||
|
initBlockSize,
|
||||||
|
maxBlockSize);
|
||||||
|
|
||||||
econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
|
econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
|
||||||
econtext->ecxt_param_list_info = estate->es_param_list_info;
|
econtext->ecxt_param_list_info = estate->es_param_list_info;
|
||||||
@ -294,6 +289,52 @@ CreateExprContext(EState *estate)
|
|||||||
return econtext;
|
return econtext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* CreateExprContext
|
||||||
|
*
|
||||||
|
* Create a context for expression evaluation within an EState.
|
||||||
|
*
|
||||||
|
* An executor run may require multiple ExprContexts (we usually make one
|
||||||
|
* for each Plan node, and a separate one for per-output-tuple processing
|
||||||
|
* such as constraint checking). Each ExprContext has its own "per-tuple"
|
||||||
|
* memory context.
|
||||||
|
*
|
||||||
|
* Note we make no assumption about the caller's memory context.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
ExprContext *
|
||||||
|
CreateExprContext(EState *estate)
|
||||||
|
{
|
||||||
|
return CreateExprContextInternal(estate, ALLOCSET_DEFAULT_SIZES);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* CreateWorkExprContext
|
||||||
|
*
|
||||||
|
* Like CreateExprContext, but specifies the AllocSet sizes to be reasonable
|
||||||
|
* in proportion to work_mem. If the maximum block allocation size is too
|
||||||
|
* large, it's easy to skip right past work_mem with a single allocation.
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
ExprContext *
|
||||||
|
CreateWorkExprContext(EState *estate)
|
||||||
|
{
|
||||||
|
Size minContextSize = ALLOCSET_DEFAULT_MINSIZE;
|
||||||
|
Size initBlockSize = ALLOCSET_DEFAULT_INITSIZE;
|
||||||
|
Size maxBlockSize = ALLOCSET_DEFAULT_MAXSIZE;
|
||||||
|
|
||||||
|
/* choose the maxBlockSize to be no larger than 1/16 of work_mem */
|
||||||
|
while (16 * maxBlockSize > work_mem * 1024L)
|
||||||
|
maxBlockSize >>= 1;
|
||||||
|
|
||||||
|
if (maxBlockSize < ALLOCSET_DEFAULT_INITSIZE)
|
||||||
|
maxBlockSize = ALLOCSET_DEFAULT_INITSIZE;
|
||||||
|
|
||||||
|
return CreateExprContextInternal(estate, minContextSize,
|
||||||
|
initBlockSize, maxBlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* CreateStandaloneExprContext
|
* CreateStandaloneExprContext
|
||||||
*
|
*
|
||||||
|
@ -3277,10 +3277,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (use_hashing)
|
if (use_hashing)
|
||||||
{
|
aggstate->hashcontext = CreateWorkExprContext(estate);
|
||||||
ExecAssignExprContext(estate, &aggstate->ss.ps);
|
|
||||||
aggstate->hashcontext = aggstate->ss.ps.ps_ExprContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecAssignExprContext(estate, &aggstate->ss.ps);
|
ExecAssignExprContext(estate, &aggstate->ss.ps);
|
||||||
|
|
||||||
|
@ -493,6 +493,7 @@ extern void end_tup_output(TupOutputState *tstate);
|
|||||||
extern EState *CreateExecutorState(void);
|
extern EState *CreateExecutorState(void);
|
||||||
extern void FreeExecutorState(EState *estate);
|
extern void FreeExecutorState(EState *estate);
|
||||||
extern ExprContext *CreateExprContext(EState *estate);
|
extern ExprContext *CreateExprContext(EState *estate);
|
||||||
|
extern ExprContext *CreateWorkExprContext(EState *estate);
|
||||||
extern ExprContext *CreateStandaloneExprContext(void);
|
extern ExprContext *CreateStandaloneExprContext(void);
|
||||||
extern void FreeExprContext(ExprContext *econtext, bool isCommit);
|
extern void FreeExprContext(ExprContext *econtext, bool isCommit);
|
||||||
extern void ReScanExprContext(ExprContext *econtext);
|
extern void ReScanExprContext(ExprContext *econtext);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user