From: Tom Lane Date: Fri, 15 Nov 2002 02:37:08 +0000 (+0000) Subject: Push qual clauses containing subplans to the back of the qual list X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=18cf40dac6d618e8e284e81e1f248e50de1393ee;p=users%2Fbernd%2Fpostgres.git Push qual clauses containing subplans to the back of the qual list at each plan node. Per gripe from Ross Reedstrom. --- diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 8723e80627..b0584b8480 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -69,6 +69,7 @@ static Node *fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index, Oid *opclass); static List *switch_outer(List *clauses); +static List *order_qual_clauses(Query *root, List *clauses); static void copy_path_costsize(Plan *dest, Path *src); static void copy_plan_costsize(Plan *dest, Plan *src); static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid); @@ -177,6 +178,9 @@ create_scan_plan(Query *root, Path *best_path) */ scan_clauses = get_actual_clauses(best_path->parent->baserestrictinfo); + /* Sort clauses into best execution order */ + scan_clauses = order_qual_clauses(root, scan_clauses); + switch (best_path->pathtype) { case T_SeqScan: @@ -1178,6 +1182,43 @@ switch_outer(List *clauses) return t_list; } +/* + * order_qual_clauses + * Given a list of qual clauses that will all be evaluated at the same + * plan node, sort the list into the order we want to check the quals + * in at runtime. + * + * Ideally the order should be driven by a combination of execution cost and + * selectivity, but unfortunately we have so little information about + * execution cost of operators that it's really hard to do anything smart. + * For now, we just move any quals that contain SubPlan references (but not + * InitPlan references) to the end of the list. + */ +static List * +order_qual_clauses(Query *root, List *clauses) +{ + List *nosubplans; + List *withsubplans; + List *l; + + /* No need to work hard if the query is subselect-free */ + if (!root->hasSubLinks) + return clauses; + + nosubplans = withsubplans = NIL; + foreach(l, clauses) + { + Node *clause = lfirst(l); + + if (contain_subplans(clause)) + withsubplans = lappend(withsubplans, clause); + else + nosubplans = lappend(nosubplans, clause); + } + + return nconc(nosubplans, withsubplans); +} + /* * Copy cost and size info from a Path node to the Plan node created from it. * The executor won't use this info, but it's needed by EXPLAIN.