Save a few bytes in pg_attribute

Change the columns attndims, attstattarget, and attinhcount from int32
to int16, and reorder a bit.  This saves some space (currently 4
bytes) in pg_attribute and tuple descriptors, which translates into
small performance benefits and/or room for new columns in pg_attribute
needed by future features.

attndims and attinhcount are never realistically used with values
larger than int16.  Just to be sure, add some overflow checks.
attstattarget is currently limited explicitly to 10000.

For consistency, pg_constraint.coninhcount is also changed like
attinhcount.

Discussion: https://www.postgresql.org/message-id/flat/d07ffc2b-e0e8-77f7-38fb-be921dff71af%40enterprisedb.com
This commit is contained in:
Peter Eisentraut 2023-03-28 09:58:14 +02:00
parent 637dce2254
commit 90189eefc1
9 changed files with 100 additions and 53 deletions

View File

@ -1164,23 +1164,6 @@
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attstattarget</structfield> <type>int4</type>
</para>
<para>
<structfield>attstattarget</structfield> controls the level of detail
of statistics accumulated for this column by
<link linkend="sql-analyze"><command>ANALYZE</command></link>.
A zero value indicates that no statistics should be collected.
A negative value says to use the system default statistics target.
The exact meaning of positive values is data type-dependent.
For scalar data types, <structfield>attstattarget</structfield>
is both the target number of <quote>most common values</quote>
to collect, and the target number of histogram bins to create.
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attlen</structfield> <type>int2</type>
@ -1202,17 +1185,6 @@
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attndims</structfield> <type>int4</type>
</para>
<para>
Number of dimensions, if the column is an array type; otherwise 0.
(Presently, the number of dimensions of an array is not enforced,
so any nonzero value effectively means <quote>it's an array</quote>.)
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attcacheoff</structfield> <type>int4</type>
@ -1237,6 +1209,17 @@
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attndims</structfield> <type>int2</type>
</para>
<para>
Number of dimensions, if the column is an array type; otherwise 0.
(Presently, the number of dimensions of an array is not enforced,
so any nonzero value effectively means <quote>it's an array</quote>.)
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attbyval</structfield> <type>bool</type>
@ -1362,7 +1345,7 @@
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attinhcount</structfield> <type>int4</type>
<structfield>attinhcount</structfield> <type>int2</type>
</para>
<para>
The number of direct ancestors this column has. A column with a
@ -1370,6 +1353,23 @@
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attstattarget</structfield> <type>int2</type>
</para>
<para>
<structfield>attstattarget</structfield> controls the level of detail
of statistics accumulated for this column by
<link linkend="sql-analyze"><command>ANALYZE</command></link>.
A zero value indicates that no statistics should be collected.
A negative value says to use the system default statistics target.
The exact meaning of positive values is data type-dependent.
For scalar data types, <structfield>attstattarget</structfield>
is both the target number of <quote>most common values</quote>
to collect, and the target number of histogram bins to create.
</para></entry>
</row>
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>attcollation</structfield> <type>oid</type>
@ -2691,7 +2691,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
<row>
<entry role="catalog_table_entry"><para role="column_definition">
<structfield>coninhcount</structfield> <type>int4</type>
<structfield>coninhcount</structfield> <type>int2</type>
</para>
<para>
The number of direct inheritance ancestors this constraint has.

View File

@ -597,6 +597,8 @@ TupleDescInitEntry(TupleDesc desc,
Assert(PointerIsValid(desc));
Assert(attributeNumber >= 1);
Assert(attributeNumber <= desc->natts);
Assert(attdim >= 0);
Assert(attdim <= PG_INT16_MAX);
/*
* initialize the attribute fields
@ -667,6 +669,8 @@ TupleDescInitBuiltinEntry(TupleDesc desc,
Assert(PointerIsValid(desc));
Assert(attributeNumber >= 1);
Assert(attributeNumber <= desc->natts);
Assert(attdim >= 0);
Assert(attdim <= PG_INT16_MAX);
/* initialize the attribute fields */
att = TupleDescAttr(desc, attributeNumber - 1);
@ -827,6 +831,10 @@ BuildDescForRelation(List *schema)
attcollation = GetColumnDefCollation(NULL, entry, atttypid);
attdim = list_length(entry->typeName->arrayBounds);
if (attdim > PG_INT16_MAX)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many array dimensions"));
if (entry->typeName->setof)
ereport(ERROR,

View File

@ -732,12 +732,11 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
slot[slotCount]->tts_values[Anum_pg_attribute_attname - 1] = NameGetDatum(&attrs->attname);
slot[slotCount]->tts_values[Anum_pg_attribute_atttypid - 1] = ObjectIdGetDatum(attrs->atttypid);
slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(attrs->attstattarget);
slot[slotCount]->tts_values[Anum_pg_attribute_attlen - 1] = Int16GetDatum(attrs->attlen);
slot[slotCount]->tts_values[Anum_pg_attribute_attnum - 1] = Int16GetDatum(attrs->attnum);
slot[slotCount]->tts_values[Anum_pg_attribute_attndims - 1] = Int32GetDatum(attrs->attndims);
slot[slotCount]->tts_values[Anum_pg_attribute_attcacheoff - 1] = Int32GetDatum(-1);
slot[slotCount]->tts_values[Anum_pg_attribute_atttypmod - 1] = Int32GetDatum(attrs->atttypmod);
slot[slotCount]->tts_values[Anum_pg_attribute_attndims - 1] = Int16GetDatum(attrs->attndims);
slot[slotCount]->tts_values[Anum_pg_attribute_attbyval - 1] = BoolGetDatum(attrs->attbyval);
slot[slotCount]->tts_values[Anum_pg_attribute_attalign - 1] = CharGetDatum(attrs->attalign);
slot[slotCount]->tts_values[Anum_pg_attribute_attstorage - 1] = CharGetDatum(attrs->attstorage);
@ -749,7 +748,8 @@ InsertPgAttributeTuples(Relation pg_attribute_rel,
slot[slotCount]->tts_values[Anum_pg_attribute_attgenerated - 1] = CharGetDatum(attrs->attgenerated);
slot[slotCount]->tts_values[Anum_pg_attribute_attisdropped - 1] = BoolGetDatum(attrs->attisdropped);
slot[slotCount]->tts_values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(attrs->attislocal);
slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(attrs->attinhcount);
slot[slotCount]->tts_values[Anum_pg_attribute_attinhcount - 1] = Int16GetDatum(attrs->attinhcount);
slot[slotCount]->tts_values[Anum_pg_attribute_attstattarget - 1] = Int16GetDatum(attrs->attstattarget);
slot[slotCount]->tts_values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(attrs->attcollation);
if (attoptions && attoptions[natts] != (Datum) 0)
slot[slotCount]->tts_values[Anum_pg_attribute_attoptions - 1] = attoptions[natts];
@ -2615,6 +2615,11 @@ MergeWithExistingConstraint(Relation rel, const char *ccname, Node *expr,
con->conislocal = true;
else
con->coninhcount++;
if (con->coninhcount < 0)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
}
if (is_no_inherit)

View File

@ -1809,7 +1809,7 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
memset(repl_repl, false, sizeof(repl_repl));
repl_repl[Anum_pg_attribute_attstattarget - 1] = true;
repl_val[Anum_pg_attribute_attstattarget - 1] = Int32GetDatum(attstattarget);
repl_val[Anum_pg_attribute_attstattarget - 1] = Int16GetDatum(attstattarget);
newTuple = heap_modify_tuple(attrTuple,
RelationGetDescr(pg_attribute),

View File

@ -190,7 +190,7 @@ CreateConstraintEntry(const char *constraintName,
values[Anum_pg_constraint_confdeltype - 1] = CharGetDatum(foreignDeleteType);
values[Anum_pg_constraint_confmatchtype - 1] = CharGetDatum(foreignMatchType);
values[Anum_pg_constraint_conislocal - 1] = BoolGetDatum(conIsLocal);
values[Anum_pg_constraint_coninhcount - 1] = Int32GetDatum(conInhCount);
values[Anum_pg_constraint_coninhcount - 1] = Int16GetDatum(conInhCount);
values[Anum_pg_constraint_connoinherit - 1] = BoolGetDatum(conNoInherit);
if (conkeyArray)
@ -805,6 +805,10 @@ ConstraintSetParentConstraint(Oid childConstrId,
constrForm->conislocal = false;
constrForm->coninhcount++;
if (constrForm->coninhcount < 0)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
constrForm->conparentid = parentConstrId;
CatalogTupleUpdate(constrRel, &tuple->t_self, newtup);

View File

@ -2650,6 +2650,10 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
*/
def->inhcount++;
if (def->inhcount < 0)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
newattmap->attnums[parent_attno - 1] = exist_attno;
}
@ -3173,6 +3177,10 @@ MergeCheckConstraint(List *constraints, char *name, Node *expr)
{
/* OK to merge */
ccon->inhcount++;
if (ccon->inhcount < 0)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
return true;
}
@ -6828,6 +6836,10 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
/* Bump the existing child att's inhcount */
childatt->attinhcount++;
if (childatt->attinhcount < 0)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple);
heap_freetuple(tuple);
@ -6919,6 +6931,10 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
attribute.attstattarget = (newattnum > 0) ? -1 : 0;
attribute.attlen = tform->typlen;
attribute.attnum = newattnum;
if (list_length(colDef->typeName->arrayBounds) > PG_INT16_MAX)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many array dimensions"));
attribute.attndims = list_length(colDef->typeName->arrayBounds);
attribute.atttypmod = typmod;
attribute.attbyval = tform->typbyval;
@ -12924,6 +12940,10 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
attTup->atttypid = targettype;
attTup->atttypmod = targettypmod;
attTup->attcollation = targetcollid;
if (list_length(typeName->arrayBounds) > PG_INT16_MAX)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many array dimensions"));
attTup->attndims = list_length(typeName->arrayBounds);
attTup->attlen = tform->typlen;
attTup->attbyval = tform->typbyval;
@ -15155,6 +15175,10 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
* later on, this change will just roll back.)
*/
childatt->attinhcount++;
if (childatt->attinhcount < 0)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
/*
* In case of partitions, we must enforce that value of attislocal
@ -15292,6 +15316,10 @@ MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel)
child_copy = heap_copytuple(child_tuple);
child_con = (Form_pg_constraint) GETSTRUCT(child_copy);
child_con->coninhcount++;
if (child_con->coninhcount < 0)
ereport(ERROR,
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("too many inheritance parents"));
/*
* In case of partitions, an inherited constraint must be

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202303231
#define CATALOG_VERSION_NO 202303281
#endif

View File

@ -52,15 +52,6 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
*/
Oid atttypid BKI_LOOKUP_OPT(pg_type);
/*
* attstattarget is the target number of statistics datapoints to collect
* during VACUUM ANALYZE of this column. A zero here indicates that we do
* not wish to collect any stats about this column. A "-1" here indicates
* that no value has been explicitly set for this column, so ANALYZE
* should use the default setting.
*/
int32 attstattarget BKI_DEFAULT(-1);
/*
* attlen is a copy of the typlen field from pg_type for this attribute.
* See atttypid comments above.
@ -82,12 +73,6 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
*/
int16 attnum;
/*
* attndims is the declared number of dimensions, if an array type,
* otherwise zero.
*/
int32 attndims;
/*
* fastgetattr() uses attcacheoff to cache byte offsets of attributes in
* heap tuples. The value actually stored in pg_attribute (-1) indicates
@ -105,6 +90,12 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
*/
int32 atttypmod BKI_DEFAULT(-1);
/*
* attndims is the declared number of dimensions, if an array type,
* otherwise zero.
*/
int16 attndims;
/*
* attbyval is a copy of the typbyval field from pg_type for this
* attribute. See atttypid comments above.
@ -165,7 +156,18 @@ CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,
bool attislocal BKI_DEFAULT(t);
/* Number of times inherited from direct parent relation(s) */
int32 attinhcount BKI_DEFAULT(0);
int16 attinhcount BKI_DEFAULT(0);
/*
* attstattarget is the target number of statistics datapoints to collect
* during VACUUM ANALYZE of this column. A zero here indicates that we do
* not wish to collect any stats about this column. A "-1" here indicates
* that no value has been explicitly set for this column, so ANALYZE
* should use the default setting.
*
* int16 is sufficient because the max value is currently 10000.
*/
int16 attstattarget BKI_DEFAULT(-1);
/* attribute's collation, if any */
Oid attcollation BKI_LOOKUP_OPT(pg_collation);

View File

@ -102,7 +102,7 @@ CATALOG(pg_constraint,2606,ConstraintRelationId)
bool conislocal;
/* Number of times inherited from direct parent relation(s) */
int32 coninhcount;
int16 coninhcount;
/* Has a local definition and cannot be inherited */
bool connoinherit;