11
11
* Portions Copyright (c) 1994, Regents of the University of California
12
12
*
13
13
* IDENTIFICATION
14
- * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.85 2007/05/31 16:57:34 tgl Exp $
14
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.86 2007/10/27 05:45:43 tgl Exp $
15
15
*
16
16
*-------------------------------------------------------------------------
17
17
*/
@@ -49,6 +49,7 @@ static PathKey *make_pathkey_from_sortinfo(PlannerInfo *root,
49
49
bool canonicalize );
50
50
static Var * find_indexkey_var (PlannerInfo * root , RelOptInfo * rel ,
51
51
AttrNumber varattno );
52
+ static bool right_merge_direction (PlannerInfo * root , PathKey * pathkey );
52
53
53
54
54
55
/****************************************************************************
@@ -1242,6 +1243,13 @@ make_inner_pathkeys_for_merge(PlannerInfo *root,
1242
1243
* overoptimistic, since joinclauses that require different other relations
1243
1244
* might never be usable at the same time, but trying to be exact is likely
1244
1245
* to be more trouble than it's worth.
1246
+ *
1247
+ * To avoid doubling the number of mergejoin paths considered, we would like
1248
+ * to consider only one of the two scan directions (ASC or DESC) as useful
1249
+ * for merging for any given target column. The choice is arbitrary unless
1250
+ * one of the directions happens to match an ORDER BY key, in which case
1251
+ * that direction should be preferred, in hopes of avoiding a final sort step.
1252
+ * right_merge_direction() implements this heuristic.
1245
1253
*/
1246
1254
int
1247
1255
pathkeys_useful_for_merging (PlannerInfo * root , RelOptInfo * rel , List * pathkeys )
@@ -1255,6 +1263,10 @@ pathkeys_useful_for_merging(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
1255
1263
bool matched = false;
1256
1264
ListCell * j ;
1257
1265
1266
+ /* If "wrong" direction, not useful for merging */
1267
+ if (!right_merge_direction (root , pathkey ))
1268
+ break ;
1269
+
1258
1270
/*
1259
1271
* First look into the EquivalenceClass of the pathkey, to see if
1260
1272
* there are any members not yet joined to the rel. If so, it's
@@ -1301,6 +1313,38 @@ pathkeys_useful_for_merging(PlannerInfo *root, RelOptInfo *rel, List *pathkeys)
1301
1313
return useful ;
1302
1314
}
1303
1315
1316
+ /*
1317
+ * right_merge_direction
1318
+ * Check whether the pathkey embodies the preferred sort direction
1319
+ * for merging its target column.
1320
+ */
1321
+ static bool
1322
+ right_merge_direction (PlannerInfo * root , PathKey * pathkey )
1323
+ {
1324
+ ListCell * l ;
1325
+
1326
+ foreach (l , root -> query_pathkeys )
1327
+ {
1328
+ PathKey * query_pathkey = (PathKey * ) lfirst (l );
1329
+
1330
+ if (pathkey -> pk_eclass == query_pathkey -> pk_eclass &&
1331
+ pathkey -> pk_opfamily == query_pathkey -> pk_opfamily )
1332
+ {
1333
+ /*
1334
+ * Found a matching query sort column. Prefer this pathkey's
1335
+ * direction iff it matches. Note that we ignore pk_nulls_first,
1336
+ * which means that a sort might be needed anyway ... but we
1337
+ * still want to prefer only one of the two possible directions,
1338
+ * and we might as well use this one.
1339
+ */
1340
+ return (pathkey -> pk_strategy == query_pathkey -> pk_strategy );
1341
+ }
1342
+ }
1343
+
1344
+ /* If no matching ORDER BY request, prefer the ASC direction */
1345
+ return (pathkey -> pk_strategy == BTLessStrategyNumber );
1346
+ }
1347
+
1304
1348
/*
1305
1349
* pathkeys_useful_for_ordering
1306
1350
* Count the number of pathkeys that are useful for meeting the
0 commit comments