Arrange to free planning memory (or most of it, anyway) at completion
of planning. This should reduce memory requirements for large joins.
This commit is contained in:
parent
c7793a731c
commit
1cffbfcb56
@ -14,7 +14,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.56 2000/07/24 03:11:01 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.57 2000/07/27 04:51:04 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -28,6 +28,7 @@
|
|||||||
#include "optimizer/paths.h"
|
#include "optimizer/paths.h"
|
||||||
#include "optimizer/planmain.h"
|
#include "optimizer/planmain.h"
|
||||||
#include "optimizer/tlist.h"
|
#include "optimizer/tlist.h"
|
||||||
|
#include "utils/memutils.h"
|
||||||
|
|
||||||
|
|
||||||
static Plan *subplanner(Query *root, List *flat_tlist, List *qual,
|
static Plan *subplanner(Query *root, List *flat_tlist, List *qual,
|
||||||
@ -176,6 +177,9 @@ subplanner(Query *root,
|
|||||||
double tuple_fraction)
|
double tuple_fraction)
|
||||||
{
|
{
|
||||||
RelOptInfo *final_rel;
|
RelOptInfo *final_rel;
|
||||||
|
Plan *resultplan;
|
||||||
|
MemoryContext mycontext;
|
||||||
|
MemoryContext oldcxt;
|
||||||
Path *cheapestpath;
|
Path *cheapestpath;
|
||||||
Path *presortedpath;
|
Path *presortedpath;
|
||||||
|
|
||||||
@ -212,6 +216,24 @@ subplanner(Query *root,
|
|||||||
*/
|
*/
|
||||||
root->query_pathkeys = canonicalize_pathkeys(root, root->query_pathkeys);
|
root->query_pathkeys = canonicalize_pathkeys(root, root->query_pathkeys);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We might allocate quite a lot of storage during planning (due to
|
||||||
|
* constructing lots of Paths), but all of it can be reclaimed after
|
||||||
|
* we generate the finished Plan tree. Work in a temporary context
|
||||||
|
* to let that happen. We make the context a child of
|
||||||
|
* TransactionCommandContext so it will be freed if error abort.
|
||||||
|
*
|
||||||
|
* Note: beware of trying to move this up to the start of this routine.
|
||||||
|
* Some of the data structures built above --- notably the pathkey
|
||||||
|
* equivalence sets --- will still be needed after this routine exits.
|
||||||
|
*/
|
||||||
|
mycontext = AllocSetContextCreate(TransactionCommandContext,
|
||||||
|
"Planner",
|
||||||
|
ALLOCSET_DEFAULT_MINSIZE,
|
||||||
|
ALLOCSET_DEFAULT_INITSIZE,
|
||||||
|
ALLOCSET_DEFAULT_MAXSIZE);
|
||||||
|
oldcxt = MemoryContextSwitchTo(mycontext);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ready to do the primary planning.
|
* Ready to do the primary planning.
|
||||||
*/
|
*/
|
||||||
@ -235,7 +257,9 @@ subplanner(Query *root,
|
|||||||
root->query_pathkeys = NIL; /* signal unordered result */
|
root->query_pathkeys = NIL; /* signal unordered result */
|
||||||
|
|
||||||
/* Make childless Result node to evaluate given tlist. */
|
/* Make childless Result node to evaluate given tlist. */
|
||||||
return (Plan *) make_result(flat_tlist, (Node *) qual, (Plan *) NULL);
|
resultplan = (Plan *) make_result(flat_tlist, (Node *) qual,
|
||||||
|
(Plan *) NULL);
|
||||||
|
goto plan_built;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NOT_USED /* fix xfunc */
|
#ifdef NOT_USED /* fix xfunc */
|
||||||
@ -295,7 +319,8 @@ subplanner(Query *root,
|
|||||||
cheapestpath->pathkeys))
|
cheapestpath->pathkeys))
|
||||||
{
|
{
|
||||||
root->query_pathkeys = cheapestpath->pathkeys;
|
root->query_pathkeys = cheapestpath->pathkeys;
|
||||||
return create_plan(root, cheapestpath);
|
resultplan = create_plan(root, cheapestpath);
|
||||||
|
goto plan_built;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -321,7 +346,8 @@ subplanner(Query *root,
|
|||||||
{
|
{
|
||||||
/* Presorted path is cheaper, use it */
|
/* Presorted path is cheaper, use it */
|
||||||
root->query_pathkeys = presortedpath->pathkeys;
|
root->query_pathkeys = presortedpath->pathkeys;
|
||||||
return create_plan(root, presortedpath);
|
resultplan = create_plan(root, presortedpath);
|
||||||
|
goto plan_built;
|
||||||
}
|
}
|
||||||
/* otherwise, doing it the hard way is still cheaper */
|
/* otherwise, doing it the hard way is still cheaper */
|
||||||
}
|
}
|
||||||
@ -334,5 +360,24 @@ subplanner(Query *root,
|
|||||||
* as an aggregate function...)
|
* as an aggregate function...)
|
||||||
*/
|
*/
|
||||||
root->query_pathkeys = cheapestpath->pathkeys;
|
root->query_pathkeys = cheapestpath->pathkeys;
|
||||||
return create_plan(root, cheapestpath);
|
resultplan = create_plan(root, cheapestpath);
|
||||||
|
|
||||||
|
plan_built:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must copy the completed plan tree and its pathkeys out of temporary
|
||||||
|
* context.
|
||||||
|
*/
|
||||||
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
|
resultplan = copyObject(resultplan);
|
||||||
|
|
||||||
|
root->query_pathkeys = copyObject(root->query_pathkeys);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we can release the Path storage.
|
||||||
|
*/
|
||||||
|
MemoryContextDelete(mycontext);
|
||||||
|
|
||||||
|
return resultplan;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user