Re: patch for large queries - Mailing list pgsql-hackers
From | Bruce Momjian |
---|---|
Subject | Re: patch for large queries |
Date | |
Msg-id | 199909272031.QAA16383@candle.pha.pa.us Whole thread Raw |
In response to | patch for large queries (Massimo Dal Zotto <dz@cs.unitn.it>) |
List | pgsql-hackers |
I think it was agreed that this patch was too ugly to apply. We have addressed the aggregate memory case already. > Hi Hackers, > > I don't like last minute patches before the final freeze, but I believe that > this one could be useful for people experiencing out-of-memory crashes while > executing queries which retrieve or use a very large number of tuples. > > The problem happens when storage is allocated for functions results used in > a large query, for example: > > select upper(name) from big_table; > select big_table.array[1] from big_table; > select count(upper(name)) from big_table; > > This patch is a dirty hack that fixes the out-of-memory problem for the most > common cases, like the above ones. It is not the final solution for the > problem but it can work for some people, so I'm posting it. > > The patch should be safe because all changes are under #ifdef. Furthermore > the feature can be enabled or disabled at runtime by the `free_tuple_memory' > options in the pg_options file. The option is disabled by default and must > be explicitly enabled at runtime to have any effect. > > To enable the patch add the follwing line to Makefile.custom: > > CUSTOM_COPT += -DFREE_TUPLE_MEMORY > > To enable the option at runtime add the following line to pg_option: > > free_tuple_memory=1 > > Here is the patch: > > *** src/include/utils/portal.h.orig Wed May 26 09:07:16 1999 > --- src/include/utils/portal.h Fri Jun 11 18:06:07 1999 > *************** > *** 80,85 **** > --- 80,89 ---- > extern PortalVariableMemory PortalGetVariableMemory(Portal portal); > extern PortalHeapMemory PortalGetHeapMemory(Portal portal); > > + #ifdef FREE_TUPLE_MEMORY > + bool PortalHeapMemoryIsValid(MemoryContext context, Pointer pointer); > + #endif > + > /* estimate of the maximum number of open portals a user would have, > * used in initially sizing the PortalHashTable in EnablePortalManager() > */ > *** src/backend/utils/mmgr/portalmem.c.orig Wed May 26 09:06:02 1999 > --- src/backend/utils/mmgr/portalmem.c Fri Jun 11 18:06:28 1999 > *************** > *** 289,294 **** > --- 289,312 ---- > } > } > > + #ifdef FREE_TUPLE_MEMORY > + /* > + * PortalHeapMemoryIsValid -- > + * > + * Check if a pointer is allocated in a memory context. > + * > + */ > + bool > + PortalHeapMemoryIsValid(MemoryContext context, Pointer pointer) > + { > + HeapMemoryBlock block = HEAPMEMBLOCK((PortalHeapMemory) context); > + > + AssertState(PointerIsValid(block)); > + > + return (AllocSetContains(&block->setData, pointer)); > + } > + #endif > + > /* ---------------- > * PortalHeapMemoryRealloc > * ---------------- > *** src/include/utils/trace.h.orig Sat Jun 5 09:00:40 1999 > --- src/include/utils/trace.h Fri Jun 11 19:01:30 1999 > *************** > *** 64,69 **** > --- 64,72 ---- > OPT_SYSLOG, /* use syslog for error messages */ > OPT_HOSTLOOKUP, /* enable hostname lookup in ps_status */ > OPT_SHOWPORTNUMBER, /* show port number in ps_status */ > + #ifdef FREE_TUPLE_MEMORY > + OPT_FREE_TUPLE_MEMORY, /* try to pfree memory for each tuple */ > + #endif > > NUM_PG_OPTIONS /* must be the last item of enum */ > }; > *************** > *** 83,91 **** > #endif /* TRACE_H */ > > /* > ! * Local variables: > ! * tab-width: 4 > ! * c-indent-level: 4 > ! * c-basic-offset: 4 > * End: > */ > --- 86,94 ---- > #endif /* TRACE_H */ > > /* > ! * Local Variables: > ! * tab-width: 4 > ! * c-indent-level: 4 > ! * c-basic-offset: 4 > * End: > */ > *** src/backend/utils/misc/trace.c.orig Sat Jun 5 09:00:37 1999 > --- src/backend/utils/misc/trace.c Fri Jun 11 19:01:31 1999 > *************** > *** 73,78 **** > --- 73,81 ---- > "syslog", /* use syslog for error messages */ > "hostlookup", /* enable hostname lookup in ps_status */ > "showportnumber", /* show port number in ps_status */ > + #ifdef FREE_TUPLE_MEMORY > + "free_tuple_memory", /* try to pfree memory for each tuple */ > + #endif > > /* NUM_PG_OPTIONS */ /* must be the last item of enum */ > }; > *************** > *** 404,412 **** > } > > /* > ! * Local variables: > ! * tab-width: 4 > ! * c-indent-level: 4 > ! * c-basic-offset: 4 > * End: > */ > --- 407,415 ---- > } > > /* > ! * Local Variables: > ! * tab-width: 4 > ! * c-indent-level: 4 > ! * c-basic-offset: 4 > * End: > */ > *** src/backend/access/common/heaptuple.c.orig Wed May 26 09:01:59 1999 > --- src/backend/access/common/heaptuple.c Fri Jun 11 19:08:33 1999 > *************** > *** 27,32 **** > --- 27,37 ---- > #include <storage/bufpage.h> > #include <utils/memutils.h> > > + #ifdef FREE_TUPLE_MEMORY > + #include <utils/portal.h> > + #include <utils/trace.h> > + #endif > + > #ifndef HAVE_MEMMOVE > #include <regex/utils.h> > #else > *************** > *** 93,98 **** > --- 98,106 ---- > int i; > int numberOfAttributes = tupleDesc->natts; > Form_pg_attribute *att = tupleDesc->attrs; > + #ifdef FREE_TUPLE_MEMORY > + bool free_tuple_memory = pg_options[OPT_FREE_TUPLE_MEMORY]; > + #endif > > if (bit != NULL) > { > *************** > *** 131,136 **** > --- 139,152 ---- > *infomask |= HEAP_HASVARLENA; > data_length = VARSIZE(DatumGetPointer(value[i])); > memmove(data, DatumGetPointer(value[i]), data_length); > + #ifdef FREE_TUPLE_MEMORY > + /* try to pfree value[i] - dz */ > + if (free_tuple_memory && > + PortalHeapMemoryIsValid(CurrentMemoryContext, > + (Pointer) value[i])) { > + pfree(value[i]); > + } > + #endif > break; > case sizeof(char): > *data = att[i]->attbyval ? > *************** > *** 147,154 **** > *((int32 *) value[i])); > break; > default: > ! memmove(data, DatumGetPointer(value[i]), > ! att[i]->attlen); > break; > } > data = (char *) att_addlength((long) data, att[i]->attlen, value[i]); > --- 163,177 ---- > *((int32 *) value[i])); > break; > default: > ! memmove(data, DatumGetPointer(value[i]), att[i]->attlen); > ! #ifdef FREE_TUPLE_MEMORY > ! /* try to pfree value[i] - dz */ > ! if (free_tuple_memory && > ! PortalHeapMemoryIsValid(CurrentMemoryContext, > ! (Pointer) value[i])) { > ! pfree(value[i]); > ! } > ! #endif > break; > } > data = (char *) att_addlength((long) data, att[i]->attlen, value[i]); > *** src/backend/executor/nodeAgg.c.orig Wed May 26 09:02:57 1999 > --- src/backend/executor/nodeAgg.c Fri Jun 11 19:10:27 1999 > *************** > *** 31,36 **** > --- 31,41 ---- > #include "utils/syscache.h" > #include "optimizer/clauses.h" > > + #ifdef FREE_TUPLE_MEMORY > + #include <utils/portal.h> > + #include <utils/trace.h> > + #endif > + > /* > * AggFuncInfo - > * keeps the transition functions information around > *************** > *** 113,119 **** > isNull1 = FALSE, > isNull2 = FALSE; > bool qual_result; > ! > > /* --------------------- > * get state info from node > --- 118,126 ---- > isNull1 = FALSE, > isNull2 = FALSE; > bool qual_result; > ! #ifdef FREE_TUPLE_MEMORY > ! bool free_tuple_memory = pg_options[OPT_FREE_TUPLE_MEMORY]; > ! #endif > > /* --------------------- > * get state info from node > *************** > *** 241,246 **** > --- 248,257 ---- > for (;;) > { > TupleTableSlot *outerslot; > + #ifdef FREE_TUPLE_MEMORY > + Oid valueType; > + bool isByValue = 0; > + #endif > > isNull = isNull1 = isNull2 = 0; > outerslot = ExecProcNode(outerPlan, (Plan *) node); > *************** > *** 293,298 **** > --- 304,334 ---- > newVal = ExecEvalExpr(aggref->target, econtext, > &isNull, &isDone); > } > + #ifdef FREE_TUPLE_MEMORY > + if (free_tuple_memory) { > + switch (nodeTag(aggref->target)) { > + case T_Const: > + isByValue = ((Const*) (aggref->target))->constbyval; > + break; > + case T_Var: > + valueType = ((Var*) (aggref->target))->vartype; > + isByValue = typeByVal(typeidType(valueType)); > + break; > + case T_Array: > + isByValue = ((Array*)(aggref->target))->arrayelembyval; > + break; > + case T_ArrayRef: > + isByValue =((ArrayRef*)(aggref->target))->refelembyval; > + break; > + case T_Expr: > + valueType = ((Expr*) (aggref->target))->typeOid; > + isByValue = typeByVal(typeidType(valueType)); > + break; > + default: > + break; > + } > + } > + #endif > > if (isNull && !aggref->usenulls) > continue; /* ignore this tuple for this agg */ > *************** > *** 353,358 **** > --- 389,404 ---- > (FmgrValues *) args, &isNull2); > Assert(!isNull2); > } > + > + #ifdef FREE_TUPLE_MEMORY > + /* try to pfree newVal if not isByValue - dz */ > + if (free_tuple_memory && !isByValue && > + PortalHeapMemoryIsValid(CurrentMemoryContext, > + (Pointer) newVal)) > + { > + pfree(newVal); > + } > + #endif > } > > /* > > > -- > Massimo Dal Zotto > > +----------------------------------------------------------------------+ > | Massimo Dal Zotto email: dz@cs.unitn.it | > | Via Marconi, 141 phone: ++39-0461534251 | > | 38057 Pergine Valsugana (TN) www: http://www.cs.unitn.it/~dz/ | > | Italy pgp: finger dz@tango.cs.unitn.it | > +----------------------------------------------------------------------+ > -- Bruce Momjian | http://www.op.net/~candle maillist@candle.pha.pa.us | (610) 853-3000+ If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania19026
pgsql-hackers by date: