www.icesr.com
IT运维工程师的摇篮

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

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

未经允许不得转载:冰点网络 » PostgreSQL 聚合函数共享申请的内存空间

分享到:更多 ()

评论 抢沙发

评论前必须登录!