Commit f0c9397f authored by Tom Lane's avatar Tom Lane

First steps towards statistics on expressional (nee functional) indexes.

This commit teaches ANALYZE to store such stats in pg_statistic, but
nothing is done yet about teaching the planner to use 'em.
Also, repair longstanding oversight in separate ANALYZE command: it
updated the pg_class.relpages and reltuples counts for the table proper,
but not for indexes.
parent 4b8f1259
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.83 2004/02/12 23:41:00 tgl Exp $
$PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.84 2004/02/15 21:01:38 tgl Exp $
-->
<chapter id="catalogs">
......@@ -3068,22 +3068,31 @@
</indexterm>
<para>
The catalog <structname>pg_statistic</structname> stores statistical data about
the contents of the database. Entries are created by
The catalog <structname>pg_statistic</structname> stores statistical data
about the contents of the database. Entries are created by
<command>ANALYZE</command> and subsequently used by the query planner.
There is one entry for each table column that has been analyzed.
Note that all the statistical data is inherently approximate,
even assuming that it is up-to-date.
</para>
<para>
<structname>pg_statistic</structname> also stores statistical data about
the values of index expressions. These are described as if they were
actual data columns; in particular, <structfield>starelid</structfield>
references the index. No entry is made for an ordinary non-expression
index column, however, since it would be redundant with the entry
for the underlying table column.
</para>
<para>
Since different kinds of statistics may be appropriate for different
kinds of data, <structname>pg_statistic</structname> is designed not
to assume very much about what sort of statistics it stores. Only
extremely general statistics (such as nullness) are given dedicated
columns in <structname>pg_statistic</structname>. Everything else
is stored in <quote>slots</quote>, which are groups of associated columns whose
content is identified by a code number in one of the slot's columns.
is stored in <quote>slots</quote>, which are groups of associated columns
whose content is identified by a code number in one of the slot's columns.
For more information see
<filename>src/include/catalog/pg_statistic.h</filename>.
</para>
......@@ -3117,7 +3126,7 @@
<entry><structfield>starelid</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
<entry>The table that the described column belongs to</entry>
<entry>The table or index that the described column belongs to</entry>
</row>
<row>
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.259 2004/02/12 23:41:02 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.260 2004/02/15 21:01:39 tgl Exp $
*
*
* INTERFACE ROUTINES
......@@ -76,7 +76,6 @@ static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin);
static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
static void StoreConstraints(Relation rel, TupleDesc tupdesc);
static void SetRelationNumChecks(Relation rel, int numchecks);
static void RemoveStatistics(Relation rel, AttrNumber attnum);
/* ----------------------------------------------------------------
......@@ -1868,7 +1867,7 @@ RemoveRelConstraints(Relation rel, const char *constrName,
* If attnum is zero, remove all entries for rel; else remove only the one
* for that column.
*/
static void
void
RemoveStatistics(Relation rel, AttrNumber attnum)
{
Relation pgstatistic;
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.227 2004/02/10 01:55:24 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.228 2004/02/15 21:01:39 tgl Exp $
*
*
* INTERFACE ROUTINES
......@@ -153,7 +153,7 @@ ConstructTupleDescriptor(Relation heapRelation,
*/
to->attnum = i + 1;
to->attstattarget = 0;
to->attstattarget = -1;
to->attcacheoff = -1;
to->attnotnull = false;
to->atthasdef = false;
......@@ -197,6 +197,7 @@ ConstructTupleDescriptor(Relation heapRelation,
to->attbyval = typeTup->typbyval;
to->attstorage = typeTup->typstorage;
to->attalign = typeTup->typalign;
to->attstattarget = -1;
to->attcacheoff = -1;
to->atttypmod = -1;
to->attislocal = true;
......@@ -753,6 +754,7 @@ index_drop(Oid indexId)
Relation userIndexRelation;
Relation indexRelation;
HeapTuple tuple;
bool hasexprs;
int i;
Assert(OidIsValid(indexId));
......@@ -786,7 +788,7 @@ index_drop(Oid indexId)
DeleteAttributeTuples(indexId);
/*
* fix INDEX relation
* fix INDEX relation, and check for expressional index
*/
indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
......@@ -796,11 +798,20 @@ index_drop(Oid indexId)
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for index %u", indexId);
hasexprs = !heap_attisnull(tuple, Anum_pg_index_indexprs);
simple_heap_delete(indexRelation, &tuple->t_self);
ReleaseSysCache(tuple);
heap_close(indexRelation, RowExclusiveLock);
/*
* if it has any expression columns, we might have stored
* statistics about them.
*/
if (hasexprs)
RemoveStatistics(userIndexRelation, 0);
/*
* flush buffer cache and physically remove the file
*/
......
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.98 2004/02/10 01:55:25 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.99 2004/02/15 21:01:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -2258,13 +2258,19 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse,
HeapTuple tuple;
Form_pg_attribute attrtuple;
rel = heap_open(myrelid, AccessExclusiveLock);
rel = relation_open(myrelid, AccessExclusiveLock);
/*
* Allow index for statistics case only
*/
if (rel->rd_rel->relkind != RELKIND_RELATION)
{
if (rel->rd_rel->relkind != RELKIND_INDEX || *flagType != 'S')
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a table",
RelationGetRelationName(rel))));
}
/* Permissions checks */
if (!pg_class_ownercheck(myrelid, GetUserId()))
......@@ -2339,7 +2345,7 @@ AlterTableAlterColumnFlags(Oid myrelid, bool recurse,
/*
* Propagate to children if desired
*/
if (recurse)
if (recurse && rel->rd_rel->relkind == RELKIND_RELATION)
{
List *child,
*children;
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.63 2003/11/29 22:40:58 pgsql Exp $
* $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.64 2004/02/15 21:01:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -69,6 +69,7 @@ extern void RemoveAttributeById(Oid relid, AttrNumber attnum);
extern void RemoveAttrDefault(Oid relid, AttrNumber attnum,
DropBehavior behavior, bool complain);
extern void RemoveAttrDefaultById(Oid attrdefId);
extern void RemoveStatistics(Relation rel, AttrNumber attnum);
extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
bool relhasoids);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.50 2004/02/13 06:39:49 tgl Exp $
* $PostgreSQL: pgsql/src/include/commands/vacuum.h,v 1.51 2004/02/15 21:01:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -106,8 +106,11 @@ typedef struct VacAttrStats
* be looked at by type-specific functions.
*/
int tupattnum; /* attribute number within tuples */
HeapTuple *rows; /* access info for fetch function */
HeapTuple *rows; /* access info for std fetch function */
TupleDesc tupDesc;
Datum *exprvals; /* access info for index fetch function */
bool *exprnulls;
int rowstride;
} VacAttrStats;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment