mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Reduce memory consumption for multi-statement query strings.
Previously, exec_simple_query always ran parse analysis, rewrite, and planning in MessageContext, allowing all the data generated thereby to persist until the end of processing of the whole query string. That's fine for single-command strings, but if a client sends many commands in a single simple-Query message, this strategy could result in annoying memory bloat, as complained of by Andreas Seltenreich. To fix, create a child context to do this work in, and reclaim it after each command. But we only do so for parsetrees that are not last in their query string. That avoids adding any memory management overhead for the typical case of a single-command string. Memory allocated for the last parsetree would be freed immediately after finishing the command string anyway. Similarly, adjust extension.c's execute_sql_string() to reclaim memory after each command. In that usage, multi-command strings are the norm, so it's a bit surprising that no one has yet complained of bloat --- especially since the bloat extended to whatever data ProcessUtility execution might leak. Amit Langote, reviewed by Julien Rouhaud Discussion: https://postgr.es/m/87ftp6l2qr.fsf@credativ.de
This commit is contained in:
@ -717,9 +717,21 @@ execute_sql_string(const char *sql)
|
||||
foreach(lc1, raw_parsetree_list)
|
||||
{
|
||||
RawStmt *parsetree = lfirst_node(RawStmt, lc1);
|
||||
MemoryContext per_parsetree_context,
|
||||
oldcontext;
|
||||
List *stmt_list;
|
||||
ListCell *lc2;
|
||||
|
||||
/*
|
||||
* We do the work for each parsetree in a short-lived context, to
|
||||
* limit the memory used when there are many commands in the string.
|
||||
*/
|
||||
per_parsetree_context =
|
||||
AllocSetContextCreate(CurrentMemoryContext,
|
||||
"execute_sql_string per-statement context",
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
oldcontext = MemoryContextSwitchTo(per_parsetree_context);
|
||||
|
||||
/* Be sure parser can see any DDL done so far */
|
||||
CommandCounterIncrement();
|
||||
|
||||
@ -772,6 +784,10 @@ execute_sql_string(const char *sql)
|
||||
|
||||
PopActiveSnapshot();
|
||||
}
|
||||
|
||||
/* Clean up per-parsetree context. */
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
MemoryContextDelete(per_parsetree_context);
|
||||
}
|
||||
|
||||
/* Be sure to advance the command counter after the last script command */
|
||||
|
Reference in New Issue
Block a user