当前位置:Gxlcms > mysql > PostgreSQL聚合函数共享申请的内存空间

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

时间:2021-07-01 10:21:17 帮助过:26人阅读

CREATE AGGREGATE Rbitmap_union2 (Rbitmap)( sfunc = myfunction, stype = mytype, FINALFUNC = myfunction_final); 在编写聚合函数时,对每一行都会重复调用指定同一函数,如果要处理的数据是累加的,那么如果不在每次调用之间共享内存空间,而是不停的申

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 */
	void	   *fn_extra;		/* extra space for use by handler */
	MemoryContext fn_mcxt;		/* 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

人气教程排行