From be05edd81296c7ec419b9af5a05460917a180b48 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 21 Feb 2000 01:13:04 +0000 Subject: [PATCH] Tweak planner to use OFFSET+LIMIT, not just LIMIT, as estimate of the portion of the query result that will be retrieved. As far as I could tell, the consensus was that we should let the planner do the best it can with a LIMIT query, and require the user to add ORDER BY if he wants consistent results from different LIMIT values. --- src/backend/optimizer/plan/planner.c | 48 ++++++++++++++++++---------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index cf400f8df1..21794fe0d3 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.75 2000/02/15 20:49:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.76 2000/02/21 01:13:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -291,30 +291,46 @@ union_planner(Query *parse, /* Initial assumption is we need all the tuples */ tuple_fraction = 0.0; /* - * Check for a LIMIT. - * - * For now, we deliberately ignore the OFFSET clause, so that - * queries with the same LIMIT and different OFFSETs will get - * the same queryplan and therefore generate consistent results - * (to the extent the planner can guarantee that, anyway). - * XXX Perhaps it would be better to use the OFFSET too, and tell - * users to specify ORDER BY if they want consistent results - * across different LIMIT queries. + * Check for a LIMIT clause. */ if (parse->limitCount != NULL) { if (IsA(parse->limitCount, Const)) { - Const *ccount = (Const *) parse->limitCount; - tuple_fraction = (double) ((int) (ccount->constvalue)); - /* the constant can legally be either 0 ("ALL") or a - * positive integer; either is consistent with our - * conventions for tuple_fraction. + Const *limitc = (Const *) parse->limitCount; + int count = (int) (limitc->constvalue); + + /* + * The constant can legally be either 0 ("ALL") or a + * positive integer. If it is not ALL, we also need + * to consider the OFFSET part of LIMIT. */ + if (count > 0) + { + tuple_fraction = (double) count; + if (parse->limitOffset != NULL) + { + if (IsA(parse->limitOffset, Const)) + { + int offset; + + limitc = (Const *) parse->limitOffset; + offset = (int) (limitc->constvalue); + if (offset > 0) + tuple_fraction += (double) offset; + } + else + { + /* It's a PARAM ... punt ... */ + tuple_fraction = 0.10; + } + } + } } else { - /* It's a PARAM ... don't know exactly what the limit + /* + * COUNT is a PARAM ... don't know exactly what the limit * will be, but for lack of a better idea assume 10% * of the plan's result is wanted. */