Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit785f709

Browse files
committed
Have the planner account for the Memoize cache key memory
The Memoize executor node stores the cache key values along with thetuple(s) which were found in the outer node which match each key value,however, when the planner tried to estimate how many entries could bestored in the cache, it didn't take into account that the cache key mustalso be stored. In many cases, this won't make a large difference as thekey is likely small in comparison to the tuple(s) being stored, however,it's not impossible to craft cases where the key could take more memorythan the tuple(s) stored for it.Here we adjust the planner so it takes into account the estimated amountof memory to store the cache key. Effectively, this change will reducethe estimated cache hit ratio when it's thought that not all items willfit in the cache, thus Memoize will become more expensive in such cases.The executor already takes into account the memory consumed by the cachekey, so here we only need to adjust the planner.Discussion:https://postgr.es/m/CAApHDvqGErGuyBfQvBQrTCHDbzLTqoiW=_G9sOzeFxWEc_7auA@mail.gmail.com
1 parent579ee5d commit785f709

File tree

1 file changed

+58
-46
lines changed

1 file changed

+58
-46
lines changed

‎src/backend/optimizer/path/costsize.c

Lines changed: 58 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ static Selectivity get_foreign_key_join_selectivity(PlannerInfo *root,
189189
staticCostappend_nonpartial_cost(List*subpaths,intnumpaths,
190190
intparallel_workers);
191191
staticvoidset_rel_width(PlannerInfo*root,RelOptInfo*rel);
192+
staticint32get_expr_width(PlannerInfo*root,constNode*expr);
192193
staticdoublerelation_byte_size(doubletuples,intwidth);
193194
staticdoublepage_size(doubletuples,intwidth);
194195
staticdoubleget_parallel_divisor(Path*path);
@@ -2481,6 +2482,7 @@ cost_memoize_rescan(PlannerInfo *root, MemoizePath *mpath,
24812482
Cost*rescan_startup_cost,Cost*rescan_total_cost)
24822483
{
24832484
EstimationInfoestinfo;
2485+
ListCell*lc;
24842486
Costinput_startup_cost=mpath->subpath->startup_cost;
24852487
Costinput_total_cost=mpath->subpath->total_cost;
24862488
doubletuples=mpath->subpath->rows;
@@ -2504,12 +2506,14 @@ cost_memoize_rescan(PlannerInfo *root, MemoizePath *mpath,
25042506
* To provide us with better estimations on how many cache entries we can
25052507
* store at once, we make a call to the executor here to ask it what
25062508
* memory overheads there are for a single cache entry.
2507-
*
2508-
* XXX we also store the cache key, but that's not accounted for here.
25092509
*/
25102510
est_entry_bytes=relation_byte_size(tuples,width)+
25112511
ExecEstimateCacheEntryOverheadBytes(tuples);
25122512

2513+
/* include the estimated width for the cache keys */
2514+
foreach(lc,mpath->param_exprs)
2515+
est_entry_bytes+=get_expr_width(root, (Node*)lfirst(lc));
2516+
25132517
/* estimate on the upper limit of cache entries we can hold at once */
25142518
est_cache_entries=floor(hash_mem_bytes /est_entry_bytes);
25152519

@@ -6021,54 +6025,13 @@ set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
60216025
{
60226026
Node*node= (Node*)lfirst(lc);
60236027

6024-
if (IsA(node,Var))
6025-
{
6026-
Var*var= (Var*)node;
6027-
int32item_width;
6028-
6029-
/* We should not see any upper-level Vars here */
6030-
Assert(var->varlevelsup==0);
6031-
6032-
/* Try to get data from RelOptInfo cache */
6033-
if (!IS_SPECIAL_VARNO(var->varno)&&
6034-
var->varno<root->simple_rel_array_size)
6035-
{
6036-
RelOptInfo*rel=root->simple_rel_array[var->varno];
6037-
6038-
if (rel!=NULL&&
6039-
var->varattno >=rel->min_attr&&
6040-
var->varattno <=rel->max_attr)
6041-
{
6042-
intndx=var->varattno-rel->min_attr;
6043-
6044-
if (rel->attr_widths[ndx]>0)
6045-
{
6046-
tuple_width+=rel->attr_widths[ndx];
6047-
continue;
6048-
}
6049-
}
6050-
}
6028+
tuple_width+=get_expr_width(root,node);
60516029

6052-
/*
6053-
* No cached data available, so estimate using just the type info.
6054-
*/
6055-
item_width=get_typavgwidth(var->vartype,var->vartypmod);
6056-
Assert(item_width>0);
6057-
tuple_width+=item_width;
6058-
}
6059-
else
6030+
/* For non-Vars, account for evaluation cost */
6031+
if (!IsA(node,Var))
60606032
{
6061-
/*
6062-
* Handle general expressions using type info.
6063-
*/
6064-
int32item_width;
60656033
QualCostcost;
60666034

6067-
item_width=get_typavgwidth(exprType(node),exprTypmod(node));
6068-
Assert(item_width>0);
6069-
tuple_width+=item_width;
6070-
6071-
/* Account for cost, too */
60726035
cost_qual_eval_node(&cost,node,root);
60736036
target->cost.startup+=cost.startup;
60746037
target->cost.per_tuple+=cost.per_tuple;
@@ -6081,6 +6044,55 @@ set_pathtarget_cost_width(PlannerInfo *root, PathTarget *target)
60816044
returntarget;
60826045
}
60836046

6047+
/*
6048+
* get_expr_width
6049+
*Estimate the width of the given expr attempting to use the width
6050+
*cached in a Var's owning RelOptInfo, else fallback on the type's
6051+
*average width when unable to or when the given Node is not a Var.
6052+
*/
6053+
staticint32
6054+
get_expr_width(PlannerInfo*root,constNode*expr)
6055+
{
6056+
int32width;
6057+
6058+
if (IsA(expr,Var))
6059+
{
6060+
constVar*var= (constVar*)expr;
6061+
6062+
/* We should not see any upper-level Vars here */
6063+
Assert(var->varlevelsup==0);
6064+
6065+
/* Try to get data from RelOptInfo cache */
6066+
if (!IS_SPECIAL_VARNO(var->varno)&&
6067+
var->varno<root->simple_rel_array_size)
6068+
{
6069+
RelOptInfo*rel=root->simple_rel_array[var->varno];
6070+
6071+
if (rel!=NULL&&
6072+
var->varattno >=rel->min_attr&&
6073+
var->varattno <=rel->max_attr)
6074+
{
6075+
intndx=var->varattno-rel->min_attr;
6076+
6077+
if (rel->attr_widths[ndx]>0)
6078+
returnrel->attr_widths[ndx];
6079+
}
6080+
}
6081+
6082+
/*
6083+
* No cached data available, so estimate using just the type info.
6084+
*/
6085+
width=get_typavgwidth(var->vartype,var->vartypmod);
6086+
Assert(width>0);
6087+
6088+
returnwidth;
6089+
}
6090+
6091+
width=get_typavgwidth(exprType(expr),exprTypmod(expr));
6092+
Assert(width>0);
6093+
returnwidth;
6094+
}
6095+
60846096
/*
60856097
* relation_byte_size
60866098
* Estimate the storage space in bytes for a given number of tuples

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp