您的位置:首页 > 数据库

PostgreSQL 聚合函数共享申请的内存空间

2016-05-06 16:10 225 查看
CREATE AGGREGATE Rbitmap_union2 (Rbitmap)
(
sfunc = myfunction,
stype = mytype,
FINALFUNC = myfunction_final
);


在编写聚合函数时,对每一行都会重复调用指定同一函数,如果要处理的数据是累加的,那么如果不在每次调用之间共享内存空间,而是不停的申请释放新的内存,那么速度会变得很慢,所以在这时共享内存是十分有用的:

PostgreSQL 有 MemoryContext 的概念,如果普通的使用 palloc 申请内存空间,系统会向 CurrentMemoryContext 申请,而据我试验猜测,聚合函数在每次调用时,都会切换 CurrentMemoryContext,所以普通的 palloc 是不能使用的。

在使用 Version 1 Calling Conventions 时,有如下宏定义, PG_FUNCTION_ARGS 是我们编写函数的实际入参:

#define PG_FUNCTION_ARGS	FunctionCallInfo fcinfo

FunctionCallInfo 是指向 FunctionCallInfoData 结构的指针:

/*
* This struct is the data actually passed to an fmgr-called function.
*/
typedef struct FunctionCallInfoData
{
FmgrInfo   *flinfo;			/* ptr to lookup info used for this call */
fmNodePtr	context;		/* pass info about context of call */
fmNodePtr	resultinfo;		/* pass or return extra info about result */
Oid			fncollation;	/* collation for function to use */
bool		isnull;			/* function must set true if result is NULL */
short		nargs;			/* # arguments actually passed */
Datum		arg[FUNC_MAX_ARGS];		/* Arguments passed to function */
bool		argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */
} FunctionCallInfoData;
其中的 flinfo 指向 FmgrInfo
typedef struct FmgrInfo
{
PGFunction	fn_addr;		/* pointer to function or handler to be called */
Oid		fn_oid;			/* OID of function (NOT of handler, if any) */
short		fn_nargs;		/* number of input args (0..FUNC_MAX_ARGS) */
bool		fn_strict;		/* function is "strict" (NULL in => NULL out) */
bool		fn_retset;		/* function returns a set */
unsigned char fn_stats;		/* collect stats if track_functions > this */
<span style="color:#ff0000;">void	   *fn_extra</span>;		/* extra space for use by handler */
<span style="color:#ff0000;">MemoryContext fn_mcxt</span>;		/* memory context to store fn_extra in */
fmNodePtr	fn_expr;		/* expression parse tree for call, or NULL */
} FmgrInfo;


我们只要在 fn_mcxt 这个 MemoryContext 下申请内存,就可以让它保持在整个聚合的过程中,申请到的内存块指针,可以存放到 fn_extra 中,也可以作为返回值和入参传递在每次调用间,最后使用 FINALFUNC 指定的函数进行最终处理。

向指定 MemoryContext - fn_mcxt 申请内存的函数如下:

MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(some_type));
它会返回一个指向申请内存空间的 void * 指针。

可以参考
src/backend/utils/adt/arrayfuncs.c 以及下列文章。


参考文章:

http://stackoverflow.com/questions/30515552/can-a-postgres-c-language-function-reference-a-stateful-variable-c-side-possibl
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: