@@ -117,13 +117,14 @@ add_paths_to_joinrel(PlannerInfo *root,
117
117
/*
118
118
* Decide whether it's sensible to generate parameterized paths for this
119
119
* joinrel, and if so, which relations such paths should require. There
120
- * is no need to create a parameterized result path unless there is a join
121
- * order restriction that prevents joining one of our input rels directly
122
- * to the parameter source rel instead of joining to the other input rel.
123
- * This restriction reduces the number of parameterized paths we have to
124
- * deal with at higher join levels, without compromising the quality of
125
- * the resulting plan. We express the restriction as a Relids set that
126
- * must overlap the parameterization of any proposed join path.
120
+ * is usually no need to create a parameterized result path unless there
121
+ * is a join order restriction that prevents joining one of our input rels
122
+ * directly to the parameter source rel instead of joining to the other
123
+ * input rel. (But see exception in try_nestloop_path.) This restriction
124
+ * reduces the number of parameterized paths we have to deal with at
125
+ * higher join levels, without compromising the quality of the resulting
126
+ * plan. We express the restriction as a Relids set that must overlap the
127
+ * parameterization of any proposed join path.
127
128
*/
128
129
foreach (lc , root -> join_info_list )
129
130
{
@@ -291,9 +292,29 @@ try_nestloop_path(PlannerInfo *root,
291
292
if (required_outer &&
292
293
!bms_overlap (required_outer , param_source_rels ))
293
294
{
294
- /* Waste no memory when we reject a path here */
295
- bms_free (required_outer );
296
- return ;
295
+ /*
296
+ * We override the param_source_rels heuristic to accept nestloop
297
+ * paths in which the outer rel satisfies some but not all of the
298
+ * inner path's parameterization. This is necessary to get good plans
299
+ * for star-schema scenarios, in which a parameterized path for a
300
+ * large table may require parameters from multiple small tables that
301
+ * will not get joined directly to each other. We can handle that by
302
+ * stacking nestloops that have the small tables on the outside; but
303
+ * this breaks the rule the param_source_rels heuristic is based on,
304
+ * namely that parameters should not be passed down across joins
305
+ * unless there's a join-order-constraint-based reason to do so. So
306
+ * ignore the param_source_rels restriction when this case applies.
307
+ */
308
+ Relids outerrelids = outer_path -> parent -> relids ;
309
+ Relids innerparams = PATH_REQ_OUTER (inner_path );
310
+
311
+ if (!(bms_overlap (innerparams , outerrelids ) &&
312
+ bms_nonempty_difference (innerparams , outerrelids )))
313
+ {
314
+ /* Waste no memory when we reject a path here */
315
+ bms_free (required_outer );
316
+ return ;
317
+ }
297
318
}
298
319
299
320
/*
0 commit comments