1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-28 18:48:04 +03:00

Add stxdinherit flag to pg_statistic_ext_data

Add pg_statistic_ext_data.stxdinherit flag, so that for each extended
statistics definition we can store two versions of data - one for the
relation alone, one for the whole inheritance tree. This is analogous to
pg_statistic.stainherit, but we failed to include such flag in catalogs
for extended statistics, and we had to work around it (see commits
859b3003de, 36c4bc6e72 and 20b9fa308e).

This changes the relationship between the two catalogs storing extended
statistics objects (pg_statistic_ext and pg_statistic_ext_data). Until
now, there was a simple 1:1 mapping - for each definition there was one
pg_statistic_ext_data row, and this row was inserted while creating the
statistics (and then updated during ANALYZE). With the stxdinherit flag,
we don't know how many rows there will be (child relations may be added
after the statistics object is defined), so there may be up to two rows.

We could make CREATE STATISTICS to always create both rows, but that
seems wasteful - without partitioning we only need stxdinherit=false
rows, and declaratively partitioned tables need only stxdinherit=true.
So we no longer initialize pg_statistic_ext_data in CREATE STATISTICS,
and instead make that a responsibility of ANALYZE. Which is what we do
for regular statistics too.

Patch by me, with extensive improvements and fixes by Justin Pryzby.

Author: Tomas Vondra, Justin Pryzby
Reviewed-by: Tomas Vondra, Justin Pryzby
Discussion: https://postgr.es/m/20210923212624.GI831%40telsasoft.com
This commit is contained in:
Tomas Vondra
2022-01-16 13:37:56 +01:00
parent e701bdd2f0
commit 269b532aef
19 changed files with 251 additions and 236 deletions

View File

@@ -75,13 +75,10 @@ CreateStatistics(CreateStatsStmt *stmt)
HeapTuple htup;
Datum values[Natts_pg_statistic_ext];
bool nulls[Natts_pg_statistic_ext];
Datum datavalues[Natts_pg_statistic_ext_data];
bool datanulls[Natts_pg_statistic_ext_data];
int2vector *stxkeys;
List *stxexprs = NIL;
Datum exprsDatum;
Relation statrel;
Relation datarel;
Relation rel = NULL;
Oid relid;
ObjectAddress parentobject,
@@ -514,28 +511,10 @@ CreateStatistics(CreateStatsStmt *stmt)
relation_close(statrel, RowExclusiveLock);
/*
* Also build the pg_statistic_ext_data tuple, to hold the actual
* statistics data.
* We used to create the pg_statistic_ext_data tuple too, but it's not clear
* what value should the stxdinherit flag have (it depends on whether the rel
* is partitioned, contains data, etc.)
*/
datarel = table_open(StatisticExtDataRelationId, RowExclusiveLock);
memset(datavalues, 0, sizeof(datavalues));
memset(datanulls, false, sizeof(datanulls));
datavalues[Anum_pg_statistic_ext_data_stxoid - 1] = ObjectIdGetDatum(statoid);
/* no statistics built yet */
datanulls[Anum_pg_statistic_ext_data_stxdndistinct - 1] = true;
datanulls[Anum_pg_statistic_ext_data_stxddependencies - 1] = true;
datanulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = true;
datanulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = true;
/* insert it into pg_statistic_ext_data */
htup = heap_form_tuple(datarel->rd_att, datavalues, datanulls);
CatalogTupleInsert(datarel, htup);
heap_freetuple(htup);
relation_close(datarel, RowExclusiveLock);
InvokeObjectPostCreateHook(StatisticExtRelationId, statoid, 0);
@@ -716,6 +695,32 @@ AlterStatistics(AlterStatsStmt *stmt)
return address;
}
/*
* Delete entry in pg_statistic_ext_data catalog. We don't know if the row
* exists, so don't error out.
*/
void
RemoveStatisticsDataById(Oid statsOid, bool inh)
{
Relation relation;
HeapTuple tup;
relation = table_open(StatisticExtDataRelationId, RowExclusiveLock);
tup = SearchSysCache2(STATEXTDATASTXOID, ObjectIdGetDatum(statsOid),
BoolGetDatum(inh));
/* We don't know if the data row for inh value exists. */
if (HeapTupleIsValid(tup))
{
CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
}
table_close(relation, RowExclusiveLock);
}
/*
* Guts of statistics object deletion.
*/
@@ -728,21 +733,12 @@ RemoveStatisticsById(Oid statsOid)
Oid relid;
/*
* First delete the pg_statistic_ext_data tuple holding the actual
* statistical data.
* First delete the pg_statistic_ext_data tuples holding the actual
* statistical data. There might be data with/without inheritance, so
* attempt deleting both.
*/
relation = table_open(StatisticExtDataRelationId, RowExclusiveLock);
tup = SearchSysCache1(STATEXTDATASTXOID, ObjectIdGetDatum(statsOid));
if (!HeapTupleIsValid(tup)) /* should not happen */
elog(ERROR, "cache lookup failed for statistics data %u", statsOid);
CatalogTupleDelete(relation, &tup->t_self);
ReleaseSysCache(tup);
table_close(relation, RowExclusiveLock);
RemoveStatisticsDataById(statsOid, true);
RemoveStatisticsDataById(statsOid, false);
/*
* Delete the pg_statistic_ext tuple. Also send out a cache inval on the