From 3779f7fd9fed8e77cb02a3ef26ab4311906377ad Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 15 Nov 2002 02:36:53 +0000 Subject: [PATCH] Push qual clauses containing subplans to the back of the qual list at each plan node. Per gripe from Ross Reedstrom. --- src/backend/optimizer/plan/createplan.c | 48 +++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index cba1b2027d..717fcfa3ce 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.121 2002/11/06 22:31:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.122 2002/11/15 02:36:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -70,6 +70,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); @@ -182,6 +183,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: @@ -359,6 +363,7 @@ create_result_plan(Query *root, ResultPath *best_path) { Result *plan; List *tlist; + List *constclauses; Plan *subplan; if (best_path->path.parent) @@ -371,7 +376,9 @@ create_result_plan(Query *root, ResultPath *best_path) else subplan = NULL; - plan = make_result(tlist, (Node *) best_path->constantqual, subplan); + constclauses = order_qual_clauses(root, best_path->constantqual); + + plan = make_result(tlist, (Node *) constclauses, subplan); return plan; } @@ -1212,6 +1219,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.