summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/costsize.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/costsize.c')
-rw-r--r--src/backend/optimizer/path/costsize.c75
1 files changed, 43 insertions, 32 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index bdfbbb18186..7dfe834b779 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -41,7 +41,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.71 2001/05/07 00:43:20 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.72 2001/05/09 00:35:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -61,12 +61,6 @@
#include "utils/syscache.h"
-/*
- * The length of a variable-length field in bytes (stupid estimate...)
- */
-#define _DEFAULT_ATTRIBUTE_WIDTH_ 12
-
-
#define LOG2(x) (log(x) / 0.693147180559945)
#define LOG6(x) (log(x) / 1.79175946922805)
@@ -90,7 +84,6 @@ bool enable_hashjoin = true;
static bool cost_qual_eval_walker(Node *node, Cost *total);
static void set_rel_width(Query *root, RelOptInfo *rel);
-static int compute_attribute_width(TargetEntry *tlistentry);
static double relation_byte_size(double tuples, int width);
static double page_size(double tuples, int width);
@@ -1082,36 +1075,54 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
/*
* set_rel_width
* Set the estimated output width of the relation.
+ *
+ * NB: this works best on base relations because it prefers to look at
+ * real Vars. It will fail to make use of pg_statistic info when applied
+ * to a subquery relation, even if the subquery outputs are simple vars
+ * that we could have gotten info for. Is it worth trying to be smarter
+ * about subqueries?
*/
static void
set_rel_width(Query *root, RelOptInfo *rel)
{
- int tuple_width = 0;
- List *tle;
+ int32 tuple_width = 0;
+ List *tllist;
- foreach(tle, rel->targetlist)
- tuple_width += compute_attribute_width((TargetEntry *) lfirst(tle));
- Assert(tuple_width >= 0);
- rel->width = tuple_width;
-}
+ foreach(tllist, rel->targetlist)
+ {
+ TargetEntry *tle = (TargetEntry *) lfirst(tllist);
+ int32 item_width;
-/*
- * compute_attribute_width
- * Given a target list entry, find the size in bytes of the attribute.
- *
- * If a field is variable-length, we make a default assumption. Would be
- * better if VACUUM recorded some stats about the average field width...
- * also, we have access to the atttypmod, but fail to use it...
- */
-static int
-compute_attribute_width(TargetEntry *tlistentry)
-{
- int width = get_typlen(tlistentry->resdom->restype);
+ /*
+ * If it's a Var, try to get statistical info from pg_statistic.
+ */
+ if (tle->expr && IsA(tle->expr, Var))
+ {
+ Var *var = (Var *) tle->expr;
+ Oid relid;
- if (width < 0)
- return _DEFAULT_ATTRIBUTE_WIDTH_;
- else
- return width;
+ relid = getrelid(var->varno, root->rtable);
+ if (relid != InvalidOid)
+ {
+ item_width = get_attavgwidth(relid, var->varattno);
+ if (item_width > 0)
+ {
+ tuple_width += item_width;
+ continue;
+ }
+ }
+ }
+ /*
+ * Not a Var, or can't find statistics for it. Estimate using
+ * just the type info.
+ */
+ item_width = get_typavgwidth(tle->resdom->restype,
+ tle->resdom->restypmod);
+ Assert(item_width > 0);
+ tuple_width += item_width;
+ }
+ Assert(tuple_width >= 0);
+ rel->width = tuple_width;
}
/*
@@ -1122,7 +1133,7 @@ compute_attribute_width(TargetEntry *tlistentry)
static double
relation_byte_size(double tuples, int width)
{
- return tuples * ((double) (width + sizeof(HeapTupleData)));
+ return tuples * ((double) MAXALIGN(width + sizeof(HeapTupleData)));
}
/*