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

Commitd57501d

Browse files
committed
improve child path generation for Runtime[Merge]Append (using get_cheapest_parameterized_child_path())
1 parent3dcf247 commitd57501d

File tree

8 files changed

+149
-136
lines changed

8 files changed

+149
-136
lines changed

‎expected/pathman_only.out

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,16 +179,26 @@ SELECT * FROM test_only.from_only_test JOIN q1 USING(val);
179179
-> CTE Scan on q1
180180
-> Custom Scan (RuntimeAppend)
181181
-> Seq Scan on from_only_test_1 from_only_test
182+
Filter: (q1.val = val)
182183
-> Seq Scan on from_only_test_2 from_only_test
184+
Filter: (q1.val = val)
183185
-> Seq Scan on from_only_test_3 from_only_test
186+
Filter: (q1.val = val)
184187
-> Seq Scan on from_only_test_4 from_only_test
188+
Filter: (q1.val = val)
185189
-> Seq Scan on from_only_test_5 from_only_test
190+
Filter: (q1.val = val)
186191
-> Seq Scan on from_only_test_6 from_only_test
192+
Filter: (q1.val = val)
187193
-> Seq Scan on from_only_test_7 from_only_test
194+
Filter: (q1.val = val)
188195
-> Seq Scan on from_only_test_8 from_only_test
196+
Filter: (q1.val = val)
189197
-> Seq Scan on from_only_test_9 from_only_test
198+
Filter: (q1.val = val)
190199
-> Seq Scan on from_only_test_10 from_only_test
191-
(15 rows)
200+
Filter: (q1.val = val)
201+
(25 rows)
192202

193203
/* should be OK */
194204
EXPLAIN (COSTS OFF)

‎src/hooks.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,27 +120,39 @@ pathman_join_pathlist_hook(PlannerInfo *root,
120120
NestPath*nest_path;/* NestLoop we're creating */
121121
ParamPathInfo*ppi;/* parameterization info */
122122
Relidsinner_required;/* required paremeterization relids */
123-
List*filtered_joinclauses=NIL;
123+
List*filtered_joinclauses=NIL,
124+
*saved_ppi_list;
124125
ListCell*rinfo_lc;
125126

126127
if (!IsA(cur_inner_path,AppendPath))
127128
continue;
128129

129130
/* Select cheapest path for outerrel */
130131
outer=outerrel->cheapest_total_path;
132+
133+
/* Wrap outer path with Unique if needed */
131134
if (saved_jointype==JOIN_UNIQUE_OUTER)
132135
{
133136
outer= (Path*)create_unique_path(root,outerrel,
134137
outer,extra->sjinfo);
135138
Assert(outer);
136139
}
137140

141+
/* No way to do this in a parameterized inner path */
142+
if (saved_jointype==JOIN_UNIQUE_INNER)
143+
return;
144+
138145
/* Make innerrel path depend on outerrel's column */
139146
inner_required=bms_union(PATH_REQ_OUTER((Path*)cur_inner_path),
140147
bms_make_singleton(outerrel->relid));
141148

149+
/* Preserve existing ppis built by get_appendrel_parampathinfo() */
150+
saved_ppi_list=innerrel->ppilist;
151+
142152
/* Get the ParamPathInfo for a parameterized path */
153+
innerrel->ppilist=NIL;
143154
ppi=get_baserel_parampathinfo(root,innerrel,inner_required);
155+
innerrel->ppilist=saved_ppi_list;
144156

145157
/* Skip ppi->ppi_clauses don't reference partition attribute */
146158
if (!(ppi&&get_partitioned_attr_clauses(ppi->ppi_clauses,
@@ -149,8 +161,8 @@ pathman_join_pathlist_hook(PlannerInfo *root,
149161
continue;
150162

151163
inner=create_runtimeappend_path(root,cur_inner_path,ppi,paramsel);
152-
if (saved_jointype==JOIN_UNIQUE_INNER)
153-
return;/*No way to do this with a parameterized inner path */
164+
if (!inner)
165+
return;/*could not build it, retreat! */
154166

155167
initial_cost_nestloop(root,&workspace,jointype,
156168
outer,inner,/* built paths */
@@ -388,13 +400,6 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
388400
Relidsinner_required=PATH_REQ_OUTER((Path*)cur_path);
389401
Path*inner_path=NULL;
390402
ParamPathInfo*ppi;
391-
List*ppi_part_clauses=NIL;
392-
393-
/* Fetch ParamPathInfo & try to extract part-related clauses */
394-
ppi=get_baserel_parampathinfo(root,rel,inner_required);
395-
if (ppi&&ppi->ppi_clauses)
396-
ppi_part_clauses=get_partitioned_attr_clauses(ppi->ppi_clauses,
397-
prel,rel->relid);
398403

399404
/* Skip if rel contains some join-related stuff or path type mismatched */
400405
if (!(IsA(cur_path,AppendPath)||IsA(cur_path,MergeAppendPath))||
@@ -403,13 +408,13 @@ pathman_rel_pathlist_hook(PlannerInfo *root,
403408
continue;
404409
}
405410

406-
/*
407-
* Skip if neither rel->baserestrictinfo nor
408-
* ppi->ppi_clauses reference partition attribute
409-
*/
410-
if (!(rel_part_clauses||ppi_part_clauses))
411+
/* Skip if rel->baserestrictinfo doesn't reference partition attribute */
412+
if (!rel_part_clauses)
411413
continue;
412414

415+
/* Get existing parameterization */
416+
ppi=get_appendrel_parampathinfo(rel,inner_required);
417+
413418
if (IsA(cur_path,AppendPath)&&pg_pathman_enable_runtimeappend)
414419
inner_path=create_runtimeappend_path(root,cur_path,
415420
ppi,paramsel);

‎src/include/pathman.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ Bitmapset *translate_col_privs(const Bitmapset *parent_privs,
123123
voidset_append_rel_pathlist(PlannerInfo*root,RelOptInfo*rel,Indexrti,
124124
PathKey*pathkeyAsc,PathKey*pathkeyDesc);
125125

126+
Path*get_cheapest_parameterized_child_path(PlannerInfo*root,RelOptInfo*rel,
127+
Relidsrequired_outer);
128+
126129

127130
typedefstruct
128131
{

‎src/include/runtimeappend.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ typedef struct
3737

3838
/* Restrictions to be checked during ReScan and Exec */
3939
List*custom_exprs;
40-
List*custom_expr_states;
4140

4241
/* All available plans \ plan states */
4342
HTAB*children_table;

‎src/nodes_common.c

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -350,22 +350,53 @@ create_append_path_common(PlannerInfo *root,
350350

351351
result->nchildren=list_length(inner_append->subpaths);
352352
result->children= (ChildScanCommon*)
353-
palloc(result->nchildren*sizeof(ChildScanCommon));
353+
palloc(result->nchildren*sizeof(ChildScanCommon));
354+
354355
i=0;
355356
foreach (lc,inner_append->subpaths)
356357
{
357-
Path*path=lfirst(lc);
358-
Indexrelindex=path->parent->relid;
358+
Path*path=(Path*)lfirst(lc);
359+
RelOptInfo*childrel=path->parent;
359360
ChildScanCommonchild;
360361

362+
/* Do we have parameterization? */
363+
if (param_info)
364+
{
365+
Relidsrequired_outer=param_info->ppi_req_outer;
366+
367+
/* Rebuild path using new 'required_outer' */
368+
path=get_cheapest_parameterized_child_path(root,childrel,
369+
required_outer);
370+
}
371+
372+
/*
373+
* We were unable to re-parameterize child path,
374+
* which means that we can't use Runtime[Merge]Append,
375+
* since its children can't evaluate join quals.
376+
*/
377+
if (!path)
378+
{
379+
intj;
380+
381+
for (j=0;j<i;j++)
382+
pfree(result->children[j]);
383+
pfree(result->children);
384+
385+
list_free_deep(result->cpath.custom_paths);
386+
387+
pfree(result);
388+
389+
returnNULL;/* notify caller */
390+
}
391+
361392
child= (ChildScanCommon)palloc(sizeof(ChildScanCommonData));
362393

363394
result->cpath.path.startup_cost+=path->startup_cost;
364395
result->cpath.path.total_cost+=path->total_cost;
365396

366397
child->content_type=CHILD_PATH;
367398
child->content.path=path;
368-
child->relid=root->simple_rte_array[relindex]->relid;
399+
child->relid=root->simple_rte_array[childrel->relid]->relid;
369400
Assert(child->relid!=InvalidOid);
370401

371402
result->cpath.custom_paths=lappend(result->cpath.custom_paths,
@@ -476,12 +507,6 @@ create_append_scan_state_common(CustomScan *node,
476507
void
477508
begin_append_common(CustomScanState*node,EState*estate,inteflags)
478509
{
479-
RuntimeAppendState*scan_state= (RuntimeAppendState*)node;
480-
481-
scan_state->custom_expr_states=
482-
(List*)ExecInitExpr((Expr*)scan_state->custom_exprs,
483-
(PlanState*)scan_state);
484-
485510
node->ss.ps.ps_TupFromTlist= false;
486511
}
487512

‎src/pg_pathman.c

Lines changed: 74 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,6 @@ static void generate_mergeappend_paths(PlannerInfo *root,
9292
PathKey*pathkeyAsc,
9393
PathKey*pathkeyDesc);
9494

95-
staticPath*get_cheapest_parameterized_child_path(PlannerInfo*root,
96-
RelOptInfo*rel,
97-
Relidsrequired_outer);
98-
9995

10096
/* We can transform Param into Const provided that 'econtext' is available */
10197
#defineIsConstValue(wcxt,node) \
@@ -293,7 +289,7 @@ append_child_relation(PlannerInfo *root, Relation parent_relation,
293289
{
294290
childquals=NIL;
295291

296-
forboth(lc1,wrappers,lc2,parent_rel->baserestrictinfo)
292+
forboth(lc1,wrappers,lc2,parent_rel->baserestrictinfo)
297293
{
298294
WrapperNode*wrap= (WrapperNode*)lfirst(lc1);
299295
Node*new_clause;
@@ -1333,78 +1329,6 @@ accumulate_append_subpath(List *subpaths, Path *path)
13331329
returnlappend(subpaths,path);
13341330
}
13351331

1336-
/*
1337-
* get_cheapest_parameterized_child_path
1338-
*Get cheapest path for this relation that has exactly the requested
1339-
*parameterization.
1340-
*
1341-
* Returns NULL if unable to create such a path.
1342-
*/
1343-
staticPath*
1344-
get_cheapest_parameterized_child_path(PlannerInfo*root,RelOptInfo*rel,
1345-
Relidsrequired_outer)
1346-
{
1347-
Path*cheapest;
1348-
ListCell*lc;
1349-
1350-
/*
1351-
* Look up the cheapest existing path with no more than the needed
1352-
* parameterization. If it has exactly the needed parameterization, we're
1353-
* done.
1354-
*/
1355-
cheapest=get_cheapest_path_for_pathkeys(rel->pathlist,
1356-
NIL,
1357-
required_outer,
1358-
TOTAL_COST);
1359-
Assert(cheapest!=NULL);
1360-
if (bms_equal(PATH_REQ_OUTER(cheapest),required_outer))
1361-
returncheapest;
1362-
1363-
/*
1364-
* Otherwise, we can "reparameterize" an existing path to match the given
1365-
* parameterization, which effectively means pushing down additional
1366-
* joinquals to be checked within the path's scan. However, some existing
1367-
* paths might check the available joinquals already while others don't;
1368-
* therefore, it's not clear which existing path will be cheapest after
1369-
* reparameterization. We have to go through them all and find out.
1370-
*/
1371-
cheapest=NULL;
1372-
foreach(lc,rel->pathlist)
1373-
{
1374-
Path*path= (Path*)lfirst(lc);
1375-
1376-
/* Can't use it if it needs more than requested parameterization */
1377-
if (!bms_is_subset(PATH_REQ_OUTER(path),required_outer))
1378-
continue;
1379-
1380-
/*
1381-
* Reparameterization can only increase the path's cost, so if it's
1382-
* already more expensive than the current cheapest, forget it.
1383-
*/
1384-
if (cheapest!=NULL&&
1385-
compare_path_costs(cheapest,path,TOTAL_COST) <=0)
1386-
continue;
1387-
1388-
/* Reparameterize if needed, then recheck cost */
1389-
if (!bms_equal(PATH_REQ_OUTER(path),required_outer))
1390-
{
1391-
path=reparameterize_path(root,path,required_outer,1.0);
1392-
if (path==NULL)
1393-
continue;/* failed to reparameterize this one */
1394-
Assert(bms_equal(PATH_REQ_OUTER(path),required_outer));
1395-
1396-
if (cheapest!=NULL&&
1397-
compare_path_costs(cheapest,path,TOTAL_COST) <=0)
1398-
continue;
1399-
}
1400-
1401-
/* We have a new best path */
1402-
cheapest=path;
1403-
}
1404-
1405-
/* Return the best path, or NULL if we found no suitable candidate */
1406-
returncheapest;
1407-
}
14081332

14091333
/*
14101334
* generate_mergeappend_paths
@@ -1945,7 +1869,6 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti,
19451869

19461870
if (parallel_workers>0)
19471871
{
1948-
19491872
/* Generate a partial append path. */
19501873
appendpath=create_append_path_compat(rel,partial_subpaths,NULL,
19511874
parallel_workers);
@@ -2006,3 +1929,76 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti,
20061929
create_append_path_compat(rel,subpaths,required_outer,0));
20071930
}
20081931
}
1932+
1933+
/*
1934+
* get_cheapest_parameterized_child_path
1935+
*Get cheapest path for this relation that has exactly the requested
1936+
*parameterization.
1937+
*
1938+
* Returns NULL if unable to create such a path.
1939+
*/
1940+
Path*
1941+
get_cheapest_parameterized_child_path(PlannerInfo*root,RelOptInfo*rel,
1942+
Relidsrequired_outer)
1943+
{
1944+
Path*cheapest;
1945+
ListCell*lc;
1946+
1947+
/*
1948+
* Look up the cheapest existing path with no more than the needed
1949+
* parameterization. If it has exactly the needed parameterization, we're
1950+
* done.
1951+
*/
1952+
cheapest=get_cheapest_path_for_pathkeys(rel->pathlist,
1953+
NIL,
1954+
required_outer,
1955+
TOTAL_COST);
1956+
Assert(cheapest!=NULL);
1957+
if (bms_equal(PATH_REQ_OUTER(cheapest),required_outer))
1958+
returncheapest;
1959+
1960+
/*
1961+
* Otherwise, we can "reparameterize" an existing path to match the given
1962+
* parameterization, which effectively means pushing down additional
1963+
* joinquals to be checked within the path's scan. However, some existing
1964+
* paths might check the available joinquals already while others don't;
1965+
* therefore, it's not clear which existing path will be cheapest after
1966+
* reparameterization. We have to go through them all and find out.
1967+
*/
1968+
cheapest=NULL;
1969+
foreach(lc,rel->pathlist)
1970+
{
1971+
Path*path= (Path*)lfirst(lc);
1972+
1973+
/* Can't use it if it needs more than requested parameterization */
1974+
if (!bms_is_subset(PATH_REQ_OUTER(path),required_outer))
1975+
continue;
1976+
1977+
/*
1978+
* Reparameterization can only increase the path's cost, so if it's
1979+
* already more expensive than the current cheapest, forget it.
1980+
*/
1981+
if (cheapest!=NULL&&
1982+
compare_path_costs(cheapest,path,TOTAL_COST) <=0)
1983+
continue;
1984+
1985+
/* Reparameterize if needed, then recheck cost */
1986+
if (!bms_equal(PATH_REQ_OUTER(path),required_outer))
1987+
{
1988+
path=reparameterize_path(root,path,required_outer,1.0);
1989+
if (path==NULL)
1990+
continue;/* failed to reparameterize this one */
1991+
Assert(bms_equal(PATH_REQ_OUTER(path),required_outer));
1992+
1993+
if (cheapest!=NULL&&
1994+
compare_path_costs(cheapest,path,TOTAL_COST) <=0)
1995+
continue;
1996+
}
1997+
1998+
/* We have a new best path */
1999+
cheapest=path;
2000+
}
2001+
2002+
/* Return the best path, or NULL if we found no suitable candidate */
2003+
returncheapest;
2004+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp