]> granicus.if.org Git - postgresql/commitdiff
Patch from Andreas: when CREATE TABLE is followed by CREATE INDEX
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 26 May 1999 22:57:39 +0000 (22:57 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 26 May 1999 22:57:39 +0000 (22:57 +0000)
before any tuples are loaded, preserve the default '1000 tuples' table
size estimate.

src/backend/catalog/heap.c
src/backend/catalog/index.c

index 89e45fb2bfc86add13b0c9a2d4f1bb3e9e903b41..1898f8f30878c8b0d043355129f5ad35b966a48a 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * 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
@@ -674,11 +674,10 @@ AddNewRelationTuple(Relation pg_class_desc,
         * enough to discourage the optimizer from using nested-loop plans.
         * With this hack, nested-loop plans will be preferred only after
         * the table has been proven to be small by VACUUM or CREATE INDEX.
-        * (NOTE: if user does CREATE TABLE, then CREATE INDEX, then loads
-        * the table, he still loses until he vacuums, because CREATE INDEX
-        * will set reltuples to zero.  Can't win 'em all.      Maintaining the
-        * stats on-the-fly would solve the problem, but the overhead of that
-        * would likely cost more than it'd save.)
+        * Maintaining the stats on-the-fly would solve the problem more cleanly,
+        * but the overhead of that would likely cost more than it'd save.
+        * (NOTE: CREATE INDEX inserts the same bogus estimates if it finds the
+        * relation has 0 rows and pages. See index.c.)
         * ----------------
         */
        new_rel_reltup->relpages = 10;          /* bogus estimates */
index 93f34ce0749d25bebcf2b951b930c25dde97d78d..0c8e9d77b789d299642dc81cee46a084f40b3653 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * 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
@@ -1291,7 +1291,6 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
        if (!RelationIsValid(pg_class))
                elog(ERROR, "UpdateStats: could not open RELATION relation");
 
-
        if (!IsBootstrapProcessingMode())
        {
                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);
 
+       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
         * place with the new values so that the cache contains the latest
         * copy.
         */
-
        whichRel->rd_rel->relhasindex = hasindex;
        whichRel->rd_rel->relpages = relpages;
        whichRel->rd_rel->reltuples = reltuples;
 
-       for (i = 0; i < Natts_pg_class; i++)
-       {
-               nulls[i] = heap_attisnull(tuple, i + 1) ? 'n' : ' ';
-               replace[i] = ' ';
-               values[i] = (Datum) NULL;
-       }
-
-       /*
-        * If reltuples wasn't supplied take an educated guess.
+       /* ----------------
+        *      Update statistics in pg_class.
+        * ----------------
         */
-       if (reltuples == 0)
-               reltuples = relpages * NTUPLES_PER_PAGE(whichRel->rd_rel->relnatts);
-
        if (IsBootstrapProcessingMode())
        {
 
@@ -1363,7 +1376,15 @@ UpdateStats(Oid relid, long reltuples, bool hasindex)
        }
        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';
                values[Anum_pg_class_relpages - 1] = (Datum) relpages;
                replace[Anum_pg_class_reltuples - 1] = 'r';
@@ -1438,12 +1459,10 @@ DefaultBuild(Relation heapRelation,
        char       *nullv;
        long            reltuples,
                                indtuples;
-
 #ifndef OMIT_PARTIAL_INDEX
        ExprContext *econtext;
        TupleTable      tupleTable;
        TupleTableSlot *slot;
-
 #endif
        Node       *predicate;
        Node       *oldPred;
@@ -1524,13 +1543,13 @@ DefaultBuild(Relation heapRelation,
        {
                reltuples++;
 
+#ifndef OMIT_PARTIAL_INDEX
                /*
                 * If oldPred != NULL, this is an EXTEND INDEX command, so skip
                 * this tuple if it was already in the existing partial index
                 */
                if (oldPred != NULL)
                {
-#ifndef OMIT_PARTIAL_INDEX
                        /* SetSlotContents(slot, heapTuple); */
                        slot->val = heapTuple;
                        if (ExecQual((List *) oldPred, econtext) == true)
@@ -1538,7 +1557,6 @@ DefaultBuild(Relation heapRelation,
                                indtuples++;
                                continue;
                        }
-#endif  /* OMIT_PARTIAL_INDEX */
                }
 
                /*
@@ -1547,13 +1565,12 @@ DefaultBuild(Relation heapRelation,
                 */
                if (predicate != NULL)
                {
-#ifndef OMIT_PARTIAL_INDEX
                        /* SetSlotContents(slot, heapTuple); */
                        slot->val = heapTuple;
                        if (ExecQual((List *) predicate, econtext) == false)
                                continue;
-#endif  /* OMIT_PARTIAL_INDEX */
                }
+#endif  /* OMIT_PARTIAL_INDEX */
 
                indtuples++;
 
@@ -1586,12 +1603,12 @@ DefaultBuild(Relation heapRelation,
 
        heap_endscan(scan);
 
+#ifndef OMIT_PARTIAL_INDEX
        if (predicate != NULL || oldPred != NULL)
        {
-#ifndef OMIT_PARTIAL_INDEX
                ExecDestroyTupleTable(tupleTable, false);
-#endif  /* OMIT_PARTIAL_INDEX */
        }
+#endif  /* OMIT_PARTIAL_INDEX */
 
        pfree(nullv);
        pfree(datum);