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

Commit4f06c68

Browse files
committed
Put back planner's ability to cache the results of mergejoinscansel(),
which I had removed in the first cut of the EquivalenceClass rewrite tosimplify that patch a little. But it's still important --- in a four-wayjoin problem mergejoinscansel() was eating about 40% of the planning timeaccording to gprof. Also, improve the EquivalenceClass code to re-usejoin RestrictInfos rather than generating fresh ones for each joinconsidered. This saves some memory space but more importantly improvesthe effectiveness of caching planning info in RestrictInfos.
1 parent45e0736 commit4f06c68

File tree

9 files changed

+285
-65
lines changed

9 files changed

+285
-65
lines changed

‎src/backend/nodes/copyfuncs.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.362 2007/01/20 20:45:38 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.363 2007/01/22 20:00:39 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -1326,6 +1326,10 @@ _copyRestrictInfo(RestrictInfo *from)
13261326
/* EquivalenceClasses are never copied, so shallow-copy the pointers */
13271327
COPY_SCALAR_FIELD(left_ec);
13281328
COPY_SCALAR_FIELD(right_ec);
1329+
COPY_SCALAR_FIELD(left_em);
1330+
COPY_SCALAR_FIELD(right_em);
1331+
/* MergeScanSelCache isn't a Node, so hard to copy; just reset cache */
1332+
newnode->scansel_cache=NIL;
13291333
COPY_SCALAR_FIELD(outer_is_left);
13301334
COPY_SCALAR_FIELD(hashjoinoperator);
13311335
COPY_SCALAR_FIELD(left_bucketsize);

‎src/backend/nodes/outfuncs.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.294 2007/01/20 20:45:38 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.295 2007/01/22 20:00:39 tgl Exp $
1212
*
1313
* NOTES
1414
* Every node type that can appear in stored rules' parsetrees *must*
@@ -1304,6 +1304,7 @@ _outEquivalenceClass(StringInfo str, EquivalenceClass *node)
13041304
WRITE_NODE_FIELD(ec_opfamilies);
13051305
WRITE_NODE_FIELD(ec_members);
13061306
WRITE_NODE_FIELD(ec_sources);
1307+
WRITE_NODE_FIELD(ec_derives);
13071308
WRITE_BITMAPSET_FIELD(ec_relids);
13081309
WRITE_BOOL_FIELD(ec_has_const);
13091310
WRITE_BOOL_FIELD(ec_has_volatile);
@@ -1354,6 +1355,8 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
13541355
WRITE_NODE_FIELD(mergeopfamilies);
13551356
WRITE_NODE_FIELD(left_ec);
13561357
WRITE_NODE_FIELD(right_ec);
1358+
WRITE_NODE_FIELD(left_em);
1359+
WRITE_NODE_FIELD(right_em);
13571360
WRITE_BOOL_FIELD(outer_is_left);
13581361
WRITE_OID_FIELD(hashjoinoperator);
13591362
}

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

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
* Portions Copyright (c) 1994, Regents of the University of California
5555
*
5656
* IDENTIFICATION
57-
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.176 2007/01/2201:35:20 tgl Exp $
57+
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.177 2007/01/2220:00:39 tgl Exp $
5858
*
5959
*-------------------------------------------------------------------------
6060
*/
@@ -108,6 +108,9 @@ boolenable_mergejoin = true;
108108
boolenable_hashjoin= true;
109109

110110

111+
staticMergeScanSelCache*cached_scansel(PlannerInfo*root,
112+
RestrictInfo*rinfo,
113+
PathKey*pathkey);
111114
staticboolcost_qual_eval_walker(Node*node,QualCost*total);
112115
staticSelectivityapprox_selectivity(PlannerInfo*root,List*quals,
113116
JoinTypejointype);
@@ -1349,9 +1352,9 @@ cost_mergejoin(MergePath *path, PlannerInfo *root)
13491352
* (unless it's an outer join, in which case the outer side has to be
13501353
* scanned all the way anyway). Estimate fraction of the left and right
13511354
* inputs that will actually need to be scanned. We use only the first
1352-
* (most significant) merge clause for this purpose.
1353-
*
1354-
*XXX mergejoinscansel is a bit expensive, can we cache its results?
1355+
* (most significant) merge clause for this purpose. Since
1356+
* mergejoinscansel() is a fairly expensive computation, we cache the
1357+
*results in the merge clause RestrictInfo.
13551358
*/
13561359
if (mergeclauses&&path->jpath.jointype!=JOIN_FULL)
13571360
{
@@ -1360,8 +1363,7 @@ cost_mergejoin(MergePath *path, PlannerInfo *root)
13601363
List*ipathkeys;
13611364
PathKey*opathkey;
13621365
PathKey*ipathkey;
1363-
Selectivityleftscansel,
1364-
rightscansel;
1366+
MergeScanSelCache*cache;
13651367

13661368
/* Get the input pathkeys to determine the sort-order details */
13671369
opathkeys=outersortkeys ?outersortkeys :outer_path->pathkeys;
@@ -1376,22 +1378,21 @@ cost_mergejoin(MergePath *path, PlannerInfo *root)
13761378
opathkey->pk_nulls_first!=ipathkey->pk_nulls_first)
13771379
elog(ERROR,"left and right pathkeys do not match in mergejoin");
13781380

1379-
mergejoinscansel(root, (Node*)firstclause->clause,
1380-
opathkey->pk_opfamily,opathkey->pk_strategy,
1381-
&leftscansel,&rightscansel);
1381+
/* Get the selectivity with caching */
1382+
cache=cached_scansel(root,firstclause,opathkey);
13821383

13831384
if (bms_is_subset(firstclause->left_relids,
13841385
outer_path->parent->relids))
13851386
{
13861387
/* left side of clause is outer */
1387-
outerscansel=leftscansel;
1388-
innerscansel=rightscansel;
1388+
outerscansel=cache->leftscansel;
1389+
innerscansel=cache->rightscansel;
13891390
}
13901391
else
13911392
{
13921393
/* left side of clause is inner */
1393-
outerscansel=rightscansel;
1394-
innerscansel=leftscansel;
1394+
outerscansel=cache->rightscansel;
1395+
innerscansel=cache->leftscansel;
13951396
}
13961397
if (path->jpath.jointype==JOIN_LEFT)
13971398
outerscansel=1.0;
@@ -1493,6 +1494,54 @@ cost_mergejoin(MergePath *path, PlannerInfo *root)
14931494
path->jpath.path.total_cost=startup_cost+run_cost;
14941495
}
14951496

1497+
/*
1498+
* run mergejoinscansel() with caching
1499+
*/
1500+
staticMergeScanSelCache*
1501+
cached_scansel(PlannerInfo*root,RestrictInfo*rinfo,PathKey*pathkey)
1502+
{
1503+
MergeScanSelCache*cache;
1504+
ListCell*lc;
1505+
Selectivityleftscansel,
1506+
rightscansel;
1507+
MemoryContextoldcontext;
1508+
1509+
/* Do we have this result already? */
1510+
foreach(lc,rinfo->scansel_cache)
1511+
{
1512+
cache= (MergeScanSelCache*)lfirst(lc);
1513+
if (cache->opfamily==pathkey->pk_opfamily&&
1514+
cache->strategy==pathkey->pk_strategy&&
1515+
cache->nulls_first==pathkey->pk_nulls_first)
1516+
returncache;
1517+
}
1518+
1519+
/* Nope, do the computation */
1520+
mergejoinscansel(root,
1521+
(Node*)rinfo->clause,
1522+
pathkey->pk_opfamily,
1523+
pathkey->pk_strategy,
1524+
pathkey->pk_nulls_first,
1525+
&leftscansel,
1526+
&rightscansel);
1527+
1528+
/* Cache the result in suitably long-lived workspace */
1529+
oldcontext=MemoryContextSwitchTo(root->planner_cxt);
1530+
1531+
cache= (MergeScanSelCache*)palloc(sizeof(MergeScanSelCache));
1532+
cache->opfamily=pathkey->pk_opfamily;
1533+
cache->strategy=pathkey->pk_strategy;
1534+
cache->nulls_first=pathkey->pk_nulls_first;
1535+
cache->leftscansel=leftscansel;
1536+
cache->rightscansel=rightscansel;
1537+
1538+
rinfo->scansel_cache=lappend(rinfo->scansel_cache,cache);
1539+
1540+
MemoryContextSwitchTo(oldcontext);
1541+
1542+
returncache;
1543+
}
1544+
14961545
/*
14971546
* cost_hashjoin
14981547
* Determines and returns the cost of joining two relations using the

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp