diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2024-01-13 18:14:53 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2024-01-13 18:14:53 +0100 |
commit | 4f622503d6de975ac87448aea5cea7de4bc140d5 (patch) | |
tree | c09756e667e5150678e8ebf9aee6c1cd5e376a96 /src/backend/commands | |
parent | 45da69371ebfc4d6982695e58791989660c1cc33 (diff) | |
download | postgresql-4f622503d6de975ac87448aea5cea7de4bc140d5.tar.gz postgresql-4f622503d6de975ac87448aea5cea7de4bc140d5.zip |
Make attstattarget nullable
This changes the pg_attribute field attstattarget into a nullable
field in the variable-length part of the row. If no value is set by
the user for attstattarget, it is now null instead of previously -1.
This saves space in pg_attribute and tuple descriptors for most
practical scenarios. (ATTRIBUTE_FIXED_PART_SIZE is reduced from 108
to 104.) Also, null is the semantically more correct value.
The ANALYZE code internally continues to represent the default
statistics target by -1, so that that code can avoid having to deal
with null values. But that is now contained to the ANALYZE code.
Only the DDL code deals with attstattarget possibly null.
For system columns, the field is now always null. The ANALYZE code
skips system columns anyway.
To set a column's statistics target to the default value, the new
command form ALTER TABLE ... SET STATISTICS DEFAULT can be used. (SET
STATISTICS -1 still works.)
Reviewed-by: Alvaro Herrera <alvherre@alvh.no-ip.org>
Discussion: https://www.postgresql.org/message-id/flat/4da8d211-d54d-44b9-9847-f2a9f1184c76@eisentraut.org
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/analyze.c | 21 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 43 |
2 files changed, 53 insertions, 11 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index deef865ce6d..a03495d6c95 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -1004,6 +1004,10 @@ static VacAttrStats * examine_attribute(Relation onerel, int attnum, Node *index_expr) { Form_pg_attribute attr = TupleDescAttr(onerel->rd_att, attnum - 1); + int attstattarget; + HeapTuple atttuple; + Datum dat; + bool isnull; HeapTuple typtuple; VacAttrStats *stats; int i; @@ -1013,15 +1017,28 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr) if (attr->attisdropped) return NULL; + /* + * Get attstattarget value. Set to -1 if null. (Analyze functions expect + * -1 to mean use default_statistics_target; see for example + * std_typanalyze.) + */ + atttuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(RelationGetRelid(onerel)), Int16GetDatum(attnum)); + if (!HeapTupleIsValid(atttuple)) + elog(ERROR, "cache lookup failed for attribute %d of relation %u", + attnum, RelationGetRelid(onerel)); + dat = SysCacheGetAttr(ATTNUM, atttuple, Anum_pg_attribute_attstattarget, &isnull); + attstattarget = isnull ? -1 : DatumGetInt16(dat); + ReleaseSysCache(atttuple); + /* Don't analyze column if user has specified not to */ - if (attr->attstattarget == 0) + if (attstattarget == 0) return NULL; /* * Create the VacAttrStats struct. */ stats = (VacAttrStats *) palloc0(sizeof(VacAttrStats)); - stats->attstattarget = attr->attstattarget; + stats->attstattarget = attstattarget; /* * When analyzing an expression index, believe the expression tree's type diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 5e558fabf65..5496f126826 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8543,10 +8543,14 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa { int newtarget; Relation attrelation; - HeapTuple tuple; + HeapTuple tuple, + newtuple; Form_pg_attribute attrtuple; AttrNumber attnum; ObjectAddress address; + Datum repl_val[Natts_pg_attribute]; + bool repl_null[Natts_pg_attribute]; + bool repl_repl[Natts_pg_attribute]; /* * We allow referencing columns by numbers only for indexes, since table @@ -8559,8 +8563,18 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot refer to non-index column by number"))); - Assert(IsA(newValue, Integer)); - newtarget = intVal(newValue); + if (newValue) + { + Assert(IsA(newValue, Integer)); + newtarget = intVal(newValue); + } + else + { + /* + * -1 was used in previous versions to represent the default setting + */ + newtarget = -1; + } /* * Limit target to a sane range @@ -8585,7 +8599,7 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa if (colName) { - tuple = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); + tuple = SearchSysCacheAttName(RelationGetRelid(rel), colName); if (!HeapTupleIsValid(tuple)) ereport(ERROR, @@ -8595,7 +8609,7 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa } else { - tuple = SearchSysCacheCopyAttNum(RelationGetRelid(rel), colNum); + tuple = SearchSysCacheAttNum(RelationGetRelid(rel), colNum); if (!HeapTupleIsValid(tuple)) ereport(ERROR, @@ -8629,16 +8643,27 @@ ATExecSetStatistics(Relation rel, const char *colName, int16 colNum, Node *newVa errhint("Alter statistics on table column instead."))); } - attrtuple->attstattarget = newtarget; - - CatalogTupleUpdate(attrelation, &tuple->t_self, tuple); + /* Build new tuple. */ + memset(repl_null, false, sizeof(repl_null)); + memset(repl_repl, false, sizeof(repl_repl)); + if (newtarget != -1) + repl_val[Anum_pg_attribute_attstattarget - 1] = newtarget; + else + repl_null[Anum_pg_attribute_attstattarget - 1] = true; + repl_repl[Anum_pg_attribute_attstattarget - 1] = true; + newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation), + repl_val, repl_null, repl_repl); + CatalogTupleUpdate(attrelation, &tuple->t_self, newtuple); InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), attrtuple->attnum); ObjectAddressSubSet(address, RelationRelationId, RelationGetRelid(rel), attnum); - heap_freetuple(tuple); + + heap_freetuple(newtuple); + + ReleaseSysCache(tuple); table_close(attrelation, RowExclusiveLock); |