什麼是 SFRM_Materialize_Preferred 以及如何使用它來編寫性能更高的函式?
研究這個問題,我看到 call 有一個
SetFunctionReturnMode
值SFRM_Materialize_Preferred
。這是什麼?這可以用來編寫性能更高的函式嗎?
SFRM_Materialize_Preferred
允許您編寫一個函式,該函式接受來自呼叫者的提示,該提示可以從自述文件中的文件Materialize
接受或ValuePerCall
模式可以同時支持
ValuePerCall
和Materialize
模式的呼叫者將SFRM_Materialize_Preferred
根據他們喜歡的模式設置或不設置。這在原始碼中被記錄為提示- 對 - 的擴展,
SFRM_Materialize
SFRM_Materialize_Random
並且SFRM_Materialize_Preferred
是關於模式的輔助標誌SFRM_Materialize
,而不是單獨的模式。您還可以看到這用於 SQL 的 PostgreSQL 函式管理器程式碼
fmgr_sql
lazyEvalOK = !(rsi->allowedModes & SFRM_Materialize_Preferred);
我自己的示範
SFRM_Materialize_Preferred
為了對其進行基準測試,我創建了自己的非常簡化的展示。你可以在我的 repo 中看到我的pg-srf-repeat
. 基本上模板歸結為這一點,Datum myfunc(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(myfunc); typedef struct { ; your function state only used in value-per-call mode } myfunc_fctx; Datum myfunc(PG_FUNCTION_ARGS) { ; get variables if (SRF_IS_FIRSTCALL()) { ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; // If we prefer materialize, get it done if ( rsinfo->allowedModes & SFRM_Materialize_Preferred ) { MemoryContext per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; MemoryContext oldcontext = MemoryContextSwitchTo(per_query_ctx); Tuplestorestate *tupstore = tuplestore_begin_heap(false, false, work_mem); rsinfo->setResult = tupstore; rsinfo->returnMode = SFRM_Materialize; TupleDesc tupdesc = rsinfo->expectedDesc; Datum values[1] = { ;stuff }; bool nulls[sizeof(values)] = {0}; # no nulls while ( times-- ) { tuplestore_putvalues(tupstore, tupdesc, values, nulls); } tuplestore_donestoring(tupstore); MemoryContextSwitchTo(oldcontext); PG_RETURN_NULL(); } // Initialize for multicall else { FuncCallContext *funcctx = SRF_FIRSTCALL_INIT(); MemoryContext oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); myfunc_fctx *fctx = (myfunc_fctx *) palloc(sizeof(myfunc_fctx)); # set myfunc_fctx funcctx->user_fctx = fctx; MemoryContextSwitchTo(oldcontext); } } FuncCallContext *funcctx = SRF_PERCALL_SETUP(); myfunc_fctx *fctx = funcctx->user_fctx; # Call this SRF_RETURN_NEXT(funcctx, fctx->object); # Or this, SRF_RETURN_DONE(funcctx); }
這通常似乎執行更快的
Materialize
orValuePerCall
並且實現的成本很小(與純實現相比)。在 Pg Python 中
**由於相關資訊的整體稀缺性,我在這裡保持這一點。**我已經確定這個宏
SRF_SHOULD_MATERIALIZE
案例實際上非常愚蠢(我已經打開了一個問題);宏的問題是並且始終是正確SRF_SHOULD_MATERIALIZE``SFRM_Materialize``SFRM_ValuePerCall
的,因此本質上它只是SFRM_Materialize_Preferred
**的較慢版本它似乎也用於
pg-python
允許您從 PostgreSQL Functions 訪問 Python 3 的項目中,但害羞的是,在所有 GitHub 上確實沒有案例。for的pg-python
宏SRF_SHOULD_MATERIALIZE
如下(見上註)#define SRF_SHOULD_MATERIALIZE(FCINFO) ( ( ((ReturnSetInfo *) FCINFO->resultinfo)->allowedModes & SFRM_Materialize ) && ( !( ((ReturnSetInfo *) FCINFO->resultinfo)->allowedModes & SFRM_ValuePerCall ) || (( ((ReturnSetInfo *) FCINFO->resultinfo)->allowedModes & SFRM_Materialize_Preferred )) ) )