mirror of
https://github.com/postgres/postgres.git
synced 2025-06-06 00:02:36 -04:00
Patch from Andreas: when CREATE TABLE is followed by CREATE INDEX
before any tuples are loaded, preserve the default '1000 tuples' table size estimate.
This commit is contained in:
parent
8eb18d874e
commit
7c8beefd5e
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.85 1999/05/25 16:08:03 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.86 1999/05/26 22:57:39 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -674,11 +674,10 @@ AddNewRelationTuple(Relation pg_class_desc,
|
|||||||
* enough to discourage the optimizer from using nested-loop plans.
|
* enough to discourage the optimizer from using nested-loop plans.
|
||||||
* With this hack, nested-loop plans will be preferred only after
|
* With this hack, nested-loop plans will be preferred only after
|
||||||
* the table has been proven to be small by VACUUM or CREATE INDEX.
|
* the table has been proven to be small by VACUUM or CREATE INDEX.
|
||||||
* (NOTE: if user does CREATE TABLE, then CREATE INDEX, then loads
|
* Maintaining the stats on-the-fly would solve the problem more cleanly,
|
||||||
* the table, he still loses until he vacuums, because CREATE INDEX
|
* but the overhead of that would likely cost more than it'd save.
|
||||||
* will set reltuples to zero. Can't win 'em all. Maintaining the
|
* (NOTE: CREATE INDEX inserts the same bogus estimates if it finds the
|
||||||
* stats on-the-fly would solve the problem, but the overhead of that
|
* relation has 0 rows and pages. See index.c.)
|
||||||
* would likely cost more than it'd save.)
|
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
new_rel_reltup->relpages = 10; /* bogus estimates */
|
new_rel_reltup->relpages = 10; /* bogus estimates */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.75 1999/05/25 16:08:06 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.76 1999/05/26 22:57:39 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -1291,7 +1291,6 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
|||||||
if (!RelationIsValid(pg_class))
|
if (!RelationIsValid(pg_class))
|
||||||
elog(ERROR, "UpdateStats: could not open RELATION relation");
|
elog(ERROR, "UpdateStats: could not open RELATION relation");
|
||||||
|
|
||||||
|
|
||||||
if (!IsBootstrapProcessingMode())
|
if (!IsBootstrapProcessingMode())
|
||||||
{
|
{
|
||||||
tuple = SearchSysCacheTupleCopy(RELOID,
|
tuple = SearchSysCacheTupleCopy(RELOID,
|
||||||
@ -1320,34 +1319,48 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* update statistics
|
* Figure values to insert.
|
||||||
|
*
|
||||||
|
* If we found zero tuples in the scan, do NOT believe it; instead put
|
||||||
|
* a bogus estimate into the statistics fields. Otherwise, the common
|
||||||
|
* pattern "CREATE TABLE; CREATE INDEX; insert data" leaves the table
|
||||||
|
* with zero size statistics until a VACUUM is done. The optimizer will
|
||||||
|
* generate very bad plans if the stats claim the table is empty when
|
||||||
|
* it is actually sizable. See also CREATE TABLE in heap.c.
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
relpages = RelationGetNumberOfBlocks(whichRel);
|
relpages = RelationGetNumberOfBlocks(whichRel);
|
||||||
|
|
||||||
|
if (reltuples == 0)
|
||||||
|
{
|
||||||
|
if (relpages == 0)
|
||||||
|
{
|
||||||
|
/* Bogus defaults for a virgin table, same as heap.c */
|
||||||
|
reltuples = 1000;
|
||||||
|
relpages = 10;
|
||||||
|
}
|
||||||
|
else if (whichRel->rd_rel->relkind == RELKIND_INDEX && relpages <= 2)
|
||||||
|
{
|
||||||
|
/* Empty index, leave bogus defaults in place */
|
||||||
|
reltuples = 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
reltuples = relpages * NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We shouldn't have to do this, but we do... Modify the reldesc in
|
* We shouldn't have to do this, but we do... Modify the reldesc in
|
||||||
* place with the new values so that the cache contains the latest
|
* place with the new values so that the cache contains the latest
|
||||||
* copy.
|
* copy.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
whichRel->rd_rel->relhasindex = hasindex;
|
whichRel->rd_rel->relhasindex = hasindex;
|
||||||
whichRel->rd_rel->relpages = relpages;
|
whichRel->rd_rel->relpages = relpages;
|
||||||
whichRel->rd_rel->reltuples = reltuples;
|
whichRel->rd_rel->reltuples = reltuples;
|
||||||
|
|
||||||
for (i = 0; i < Natts_pg_class; i++)
|
/* ----------------
|
||||||
{
|
* Update statistics in pg_class.
|
||||||
nulls[i] = heap_attisnull(tuple, i + 1) ? 'n' : ' ';
|
* ----------------
|
||||||
replace[i] = ' ';
|
|
||||||
values[i] = (Datum) NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If reltuples wasn't supplied take an educated guess.
|
|
||||||
*/
|
*/
|
||||||
if (reltuples == 0)
|
|
||||||
reltuples = relpages * NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts);
|
|
||||||
|
|
||||||
if (IsBootstrapProcessingMode())
|
if (IsBootstrapProcessingMode())
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1363,7 +1376,15 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* during normal processing, work harder */
|
/* During normal processing, must work harder. */
|
||||||
|
|
||||||
|
for (i = 0; i < Natts_pg_class; i++)
|
||||||
|
{
|
||||||
|
nulls[i] = heap_attisnull(tuple, i + 1) ? 'n' : ' ';
|
||||||
|
replace[i] = ' ';
|
||||||
|
values[i] = (Datum) NULL;
|
||||||
|
}
|
||||||
|
|
||||||
replace[Anum_pg_class_relpages - 1] = 'r';
|
replace[Anum_pg_class_relpages - 1] = 'r';
|
||||||
values[Anum_pg_class_relpages - 1] = (Datum) relpages;
|
values[Anum_pg_class_relpages - 1] = (Datum) relpages;
|
||||||
replace[Anum_pg_class_reltuples - 1] = 'r';
|
replace[Anum_pg_class_reltuples - 1] = 'r';
|
||||||
@ -1438,12 +1459,10 @@ DefaultBuild(Relation heapRelation,
|
|||||||
char *nullv;
|
char *nullv;
|
||||||
long reltuples,
|
long reltuples,
|
||||||
indtuples;
|
indtuples;
|
||||||
|
|
||||||
#ifndef OMIT_PARTIAL_INDEX
|
#ifndef OMIT_PARTIAL_INDEX
|
||||||
ExprContext *econtext;
|
ExprContext *econtext;
|
||||||
TupleTable tupleTable;
|
TupleTable tupleTable;
|
||||||
TupleTableSlot *slot;
|
TupleTableSlot *slot;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Node *predicate;
|
Node *predicate;
|
||||||
Node *oldPred;
|
Node *oldPred;
|
||||||
@ -1524,13 +1543,13 @@ DefaultBuild(Relation heapRelation,
|
|||||||
{
|
{
|
||||||
reltuples++;
|
reltuples++;
|
||||||
|
|
||||||
|
#ifndef OMIT_PARTIAL_INDEX
|
||||||
/*
|
/*
|
||||||
* If oldPred != NULL, this is an EXTEND INDEX command, so skip
|
* If oldPred != NULL, this is an EXTEND INDEX command, so skip
|
||||||
* this tuple if it was already in the existing partial index
|
* this tuple if it was already in the existing partial index
|
||||||
*/
|
*/
|
||||||
if (oldPred != NULL)
|
if (oldPred != NULL)
|
||||||
{
|
{
|
||||||
#ifndef OMIT_PARTIAL_INDEX
|
|
||||||
/* SetSlotContents(slot, heapTuple); */
|
/* SetSlotContents(slot, heapTuple); */
|
||||||
slot->val = heapTuple;
|
slot->val = heapTuple;
|
||||||
if (ExecQual((List *) oldPred, econtext) == true)
|
if (ExecQual((List *) oldPred, econtext) == true)
|
||||||
@ -1538,7 +1557,6 @@ DefaultBuild(Relation heapRelation,
|
|||||||
indtuples++;
|
indtuples++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif /* OMIT_PARTIAL_INDEX */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1547,13 +1565,12 @@ DefaultBuild(Relation heapRelation,
|
|||||||
*/
|
*/
|
||||||
if (predicate != NULL)
|
if (predicate != NULL)
|
||||||
{
|
{
|
||||||
#ifndef OMIT_PARTIAL_INDEX
|
|
||||||
/* SetSlotContents(slot, heapTuple); */
|
/* SetSlotContents(slot, heapTuple); */
|
||||||
slot->val = heapTuple;
|
slot->val = heapTuple;
|
||||||
if (ExecQual((List *) predicate, econtext) == false)
|
if (ExecQual((List *) predicate, econtext) == false)
|
||||||
continue;
|
continue;
|
||||||
#endif /* OMIT_PARTIAL_INDEX */
|
|
||||||
}
|
}
|
||||||
|
#endif /* OMIT_PARTIAL_INDEX */
|
||||||
|
|
||||||
indtuples++;
|
indtuples++;
|
||||||
|
|
||||||
@ -1586,12 +1603,12 @@ DefaultBuild(Relation heapRelation,
|
|||||||
|
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
|
|
||||||
|
#ifndef OMIT_PARTIAL_INDEX
|
||||||
if (predicate != NULL || oldPred != NULL)
|
if (predicate != NULL || oldPred != NULL)
|
||||||
{
|
{
|
||||||
#ifndef OMIT_PARTIAL_INDEX
|
|
||||||
ExecDestroyTupleTable(tupleTable, false);
|
ExecDestroyTupleTable(tupleTable, false);
|
||||||
#endif /* OMIT_PARTIAL_INDEX */
|
|
||||||
}
|
}
|
||||||
|
#endif /* OMIT_PARTIAL_INDEX */
|
||||||
|
|
||||||
pfree(nullv);
|
pfree(nullv);
|
||||||
pfree(datum);
|
pfree(datum);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user