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

Commita911013

Browse files
committed
Remember pathkey's source expression.
To consistently estimate the number of groups using the pathkeys list in thesorting operation, we need to identify the expression used as a sort key.Pathkey refers to the equivalence class, which can contain a wide variety ofexpressions. To somehow stabilise the expression's choice, save the link to theorigin expression, triggering the PathKey creation. While this approach doesn'talways guarantee the right choice, it makes dependence on the SQL string lessobvious.
1 parent4058c72 commita911013

File tree

5 files changed

+59
-13
lines changed

5 files changed

+59
-13
lines changed

‎contrib/postgres_fdw/postgres_fdw.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,7 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
976976
foreach(lc,useful_eclass_list)
977977
{
978978
EquivalenceClass*cur_ec=lfirst(lc);
979+
EquivalenceMember*em;
979980
PathKey*pathkey;
980981

981982
/* If redundant with what we did above, skip it. */
@@ -988,14 +989,15 @@ get_useful_pathkeys_for_relation(PlannerInfo *root, RelOptInfo *rel)
988989
continue;
989990

990991
/* If no pushable expression for this rel, skip it. */
991-
if (find_em_for_rel(root,cur_ec,rel)==NULL)
992+
if ((em=find_em_for_rel(root,cur_ec,rel))==NULL)
992993
continue;
993994

994995
/* Looks like we can generate a pathkey, so let's do it. */
995996
pathkey=make_canonical_pathkey(root,cur_ec,
996997
linitial_oid(cur_ec->ec_opfamilies),
997998
BTLessStrategyNumber,
998-
false);
999+
false,
1000+
em->em_expr);/* TODO */
9991001
useful_pathkeys_list=lappend(useful_pathkeys_list,
10001002
list_make1(pathkey));
10011003
}

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

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,21 +2019,41 @@ cost_incremental_sort(Path *path,
20192019
foreach(l,pathkeys)
20202020
{
20212021
PathKey*key= (PathKey*)lfirst(l);
2022-
EquivalenceMember*member= (EquivalenceMember*)
2023-
linitial(key->pk_eclass->ec_members);
2022+
2023+
#ifdefUSE_ASSERT_CHECKING
2024+
ListCell*lc;
2025+
2026+
/* Be paranoid, but caring about performace don't check on prod */
2027+
foreach(lc,key->pk_eclass->ec_members)
2028+
{
2029+
if (find_ec_member_matching_expr(
2030+
key->pk_eclass,key->source_expr,
2031+
pull_varnos(root, (Node*)key->source_expr)))
2032+
break;
2033+
}
2034+
if (!lc)
2035+
/*
2036+
* XXX: Can we build PathKey over derived expression and does it
2037+
* trigger this error?
2038+
*/
2039+
elog(ERROR,"PathKey source expression must be a part of EQ class");
2040+
#endif
2041+
2042+
/* Reassure ourselves no one created pathkeys alternative way */
2043+
Assert(key->source_expr!=NULL);
20242044

20252045
/*
20262046
* Check if the expression contains Var with "varno 0" so that we
20272047
* don't call estimate_num_groups in that case.
20282048
*/
2029-
if (bms_is_member(0,pull_varnos(root, (Node*)member->em_expr)))
2049+
if (bms_is_member(0,pull_varnos(root, (Node*)key->source_expr)))
20302050
{
20312051
unknown_varno= true;
20322052
break;
20332053
}
20342054

20352055
/* expression not containing any Vars with "varno 0" */
2036-
presortedExprs=lappend(presortedExprs,member->em_expr);
2056+
presortedExprs=lappend(presortedExprs,key->source_expr);
20372057

20382058
if (foreach_current_index(l)+1 >=presorted_keys)
20392059
break;

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

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static bool right_merge_direction(PlannerInfo *root, PathKey *pathkey);
5454
PathKey*
5555
make_canonical_pathkey(PlannerInfo*root,
5656
EquivalenceClass*eclass,Oidopfamily,
57-
intstrategy,boolnulls_first)
57+
intstrategy,boolnulls_first,Expr*src_expr)
5858
{
5959
PathKey*pk;
6060
ListCell*lc;
@@ -89,6 +89,7 @@ make_canonical_pathkey(PlannerInfo *root,
8989
pk->pk_opfamily=opfamily;
9090
pk->pk_strategy=strategy;
9191
pk->pk_nulls_first=nulls_first;
92+
pk->source_expr=src_expr;
9293

9394
root->canon_pathkeys=lappend(root->canon_pathkeys,pk);
9495

@@ -241,7 +242,7 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
241242

242243
/* And finally we can find or create a PathKey node */
243244
returnmake_canonical_pathkey(root,eclass,opfamily,
244-
strategy,nulls_first);
245+
strategy,nulls_first,expr);
245246
}
246247

247248
/*
@@ -1117,7 +1118,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
11171118
outer_ec,
11181119
sub_pathkey->pk_opfamily,
11191120
sub_pathkey->pk_strategy,
1120-
sub_pathkey->pk_nulls_first);
1121+
sub_pathkey->pk_nulls_first,
1122+
(Expr*)outer_var);
11211123
}
11221124
}
11231125
else
@@ -1199,7 +1201,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
11991201
outer_ec,
12001202
sub_pathkey->pk_opfamily,
12011203
sub_pathkey->pk_strategy,
1202-
sub_pathkey->pk_nulls_first);
1204+
sub_pathkey->pk_nulls_first,
1205+
(Expr*)outer_var);
12031206
/* score = # of equivalence peers */
12041207
score=list_length(outer_ec->ec_members)-1;
12051208
/* +1 if it matches the proper query_pathkeys item */
@@ -1646,6 +1649,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
16461649
List*pathkeys=NIL;
16471650
intnClauses=list_length(mergeclauses);
16481651
EquivalenceClass**ecs;
1652+
Expr**exprs;
16491653
int*scores;
16501654
intnecs;
16511655
ListCell*lc;
@@ -1660,6 +1664,7 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
16601664
* duplicates) and their "popularity" scores.
16611665
*/
16621666
ecs= (EquivalenceClass**)palloc(nClauses*sizeof(EquivalenceClass*));
1667+
exprs= (Expr**)palloc(nClauses*sizeof(Expr*));
16631668
scores= (int*)palloc(nClauses*sizeof(int));
16641669
necs=0;
16651670

@@ -1669,14 +1674,21 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
16691674
EquivalenceClass*oeclass;
16701675
intscore;
16711676
ListCell*lc2;
1677+
Expr*expr;
16721678

16731679
/* get the outer eclass */
16741680
update_mergeclause_eclasses(root,rinfo);
16751681

16761682
if (rinfo->outer_is_left)
1683+
{
16771684
oeclass=rinfo->left_ec;
1685+
expr= (Expr*)linitial(((OpExpr*)rinfo->clause)->args);
1686+
}
16781687
else
1688+
{
16791689
oeclass=rinfo->right_ec;
1690+
expr= (Expr*)lsecond(((OpExpr*)rinfo->clause)->args);
1691+
}
16801692

16811693
/* reject duplicates */
16821694
for (j=0;j<necs;j++)
@@ -1700,6 +1712,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
17001712
}
17011713

17021714
ecs[necs]=oeclass;
1715+
exprs[necs]=expr;
1716+
17031717
scores[necs]=score;
17041718
necs++;
17051719
}
@@ -1801,7 +1815,8 @@ select_outer_pathkeys_for_merge(PlannerInfo *root,
18011815
ec,
18021816
linitial_oid(ec->ec_opfamilies),
18031817
BTLessStrategyNumber,
1804-
false);
1818+
false,
1819+
exprs[best_j]);
18051820
/* can't be redundant because no duplicate ECs */
18061821
Assert(!pathkey_is_redundant(pathkey,pathkeys));
18071822
pathkeys=lappend(pathkeys,pathkey);
@@ -1855,18 +1870,23 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
18551870
EquivalenceClass*oeclass;
18561871
EquivalenceClass*ieclass;
18571872
PathKey*pathkey;
1873+
Expr*src_expr;
18581874

18591875
update_mergeclause_eclasses(root,rinfo);
18601876

1877+
Assert(IsA(rinfo->clause,OpExpr)&&rinfo->orclause==NULL);
1878+
18611879
if (rinfo->outer_is_left)
18621880
{
18631881
oeclass=rinfo->left_ec;
18641882
ieclass=rinfo->right_ec;
1883+
src_expr= (Expr*)lsecond(((OpExpr*)rinfo->clause)->args);
18651884
}
18661885
else
18671886
{
18681887
oeclass=rinfo->right_ec;
18691888
ieclass=rinfo->left_ec;
1889+
src_expr= (Expr*)linitial(((OpExpr*)rinfo->clause)->args);
18701890
}
18711891

18721892
/* outer eclass should match current or next pathkeys */
@@ -1894,7 +1914,8 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
18941914
ieclass,
18951915
opathkey->pk_opfamily,
18961916
opathkey->pk_strategy,
1897-
opathkey->pk_nulls_first);
1917+
opathkey->pk_nulls_first,
1918+
src_expr);
18981919

18991920
/*
19001921
* Don't generate redundant pathkeys (which can happen if multiple

‎src/include/nodes/pathnodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,8 @@ typedef struct PathKey
14691469
Oidpk_opfamily;/* btree opfamily defining the ordering */
14701470
intpk_strategy;/* sort direction (ASC or DESC) */
14711471
boolpk_nulls_first;/* do NULLs come before normal values? */
1472+
1473+
Expr*source_expr;/* Expression, which triggered this creation */
14721474
}PathKey;
14731475

14741476
/*

‎src/include/optimizer/paths.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ extern bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel);
264264
externList*append_pathkeys(List*target,List*source);
265265
externPathKey*make_canonical_pathkey(PlannerInfo*root,
266266
EquivalenceClass*eclass,Oidopfamily,
267-
intstrategy,boolnulls_first);
267+
intstrategy,boolnulls_first,
268+
Expr*src_expr);
268269
externvoidadd_paths_to_append_rel(PlannerInfo*root,RelOptInfo*rel,
269270
List*live_childrels);
270271

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp