diff options
Diffstat (limited to 'src/backend/optimizer/util/plancat.c')
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 86 |
1 files changed, 65 insertions, 21 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index ad71d3a4f9e..7ffa11588d7 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -46,6 +46,7 @@ int constraint_exclusion = CONSTRAINT_EXCLUSION_PARTITION; get_relation_info_hook_type get_relation_info_hook = NULL; +static int32 get_rel_data_width(Relation rel, int32 *attr_widths); static List *get_relation_constraints(PlannerInfo *root, Oid relationObjectId, RelOptInfo *rel, bool include_notnull); @@ -406,28 +407,9 @@ estimate_rel_size(Relation rel, int32 *attr_widths, * platform dependencies in the default plans which are kind * of a headache for regression testing. */ - int32 tuple_width = 0; - int i; + int32 tuple_width; - for (i = 1; i <= RelationGetNumberOfAttributes(rel); i++) - { - Form_pg_attribute att = rel->rd_att->attrs[i - 1]; - int32 item_width; - - if (att->attisdropped) - continue; - /* This should match set_rel_width() in costsize.c */ - item_width = get_attavgwidth(RelationGetRelid(rel), i); - if (item_width <= 0) - { - item_width = get_typavgwidth(att->atttypid, - att->atttypmod); - Assert(item_width > 0); - } - if (attr_widths != NULL) - attr_widths[i] = item_width; - tuple_width += item_width; - } + tuple_width = get_rel_data_width(rel, attr_widths); tuple_width += sizeof(HeapTupleHeaderData); tuple_width += sizeof(ItemPointerData); /* note: integer division is intentional here */ @@ -450,6 +432,68 @@ estimate_rel_size(Relation rel, int32 *attr_widths, /* + * get_rel_data_width + * + * Estimate the average width of (the data part of) the relation's tuples. + * If attr_widths isn't NULL, also store per-column width estimates into + * that array. + * + * Currently we ignore dropped columns. Ideally those should be included + * in the result, but we haven't got any way to get info about them; and + * since they might be mostly NULLs, treating them as zero-width is not + * necessarily the wrong thing anyway. + */ +static int32 +get_rel_data_width(Relation rel, int32 *attr_widths) +{ + int32 tuple_width = 0; + int i; + + for (i = 1; i <= RelationGetNumberOfAttributes(rel); i++) + { + Form_pg_attribute att = rel->rd_att->attrs[i - 1]; + int32 item_width; + + if (att->attisdropped) + continue; + /* This should match set_rel_width() in costsize.c */ + item_width = get_attavgwidth(RelationGetRelid(rel), i); + if (item_width <= 0) + { + item_width = get_typavgwidth(att->atttypid, att->atttypmod); + Assert(item_width > 0); + } + if (attr_widths != NULL) + attr_widths[i] = item_width; + tuple_width += item_width; + } + + return tuple_width; +} + +/* + * get_relation_data_width + * + * External API for get_rel_data_width + */ +int32 +get_relation_data_width(Oid relid) +{ + int32 result; + Relation relation; + + /* As above, assume relation is already locked */ + relation = heap_open(relid, NoLock); + + result = get_rel_data_width(relation, NULL); + + heap_close(relation, NoLock); + + return result; +} + + +/* * get_relation_constraints * * Retrieve the CHECK constraint expressions of the given relation. |