]> granicus.if.org Git - postgresql/commitdiff
In DeleteAttributeTuples, use a single indexscan instead of the multiple
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Jul 2002 21:08:08 +0000 (21:08 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 14 Jul 2002 21:08:08 +0000 (21:08 +0000)
scans that will most likely be caused by SearchSysCache probes.  Also,
share some code between index deletion and table deletion.

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

index 207090ae70aba4e6df8f7196eba6f74776d5bd64..48f7cae1aa0e4a87f30be1179c6750cb55e843fb 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.205 2002/07/12 18:43:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.206 2002/07/14 21:08:08 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -66,13 +66,11 @@ static void AddNewRelationTuple(Relation pg_class_desc,
                                        Relation new_rel_desc,
                                        Oid new_rel_oid, Oid new_type_oid,
                                        char relkind, bool relhasoids);
-static void DeleteAttributeTuples(Relation rel);
-static void DeleteRelationTuple(Relation rel);
-static void RelationRemoveInheritance(Relation relation);
 static void AddNewRelationType(const char *typeName,
                                                           Oid typeNamespace,
                                                           Oid new_rel_oid,
                                                           Oid new_type_oid);
+static void RelationRemoveInheritance(Relation relation);
 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);
@@ -793,193 +791,72 @@ RelationRemoveInheritance(Relation relation)
 
 /*
  *             DeleteRelationTuple
+ *
+ * Remove pg_class row for the given relid.
+ *
+ * Note: this is shared by relation deletion and index deletion.  It's
+ * not intended for use anyplace else.
  */
-static void
-DeleteRelationTuple(Relation rel)
+void
+DeleteRelationTuple(Oid relid)
 {
        Relation        pg_class_desc;
        HeapTuple       tup;
 
-       /*
-        * open pg_class
-        */
+       /* Grab an appropriate lock on the pg_class relation */
        pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
 
-       tup = SearchSysCacheCopy(RELOID,
-                                                        ObjectIdGetDatum(rel->rd_id),
-                                                        0, 0, 0);
+       tup = SearchSysCache(RELOID,
+                                                ObjectIdGetDatum(relid),
+                                                0, 0, 0);
        if (!HeapTupleIsValid(tup))
-               elog(ERROR, "Relation \"%s\" does not exist",
-                        RelationGetRelationName(rel));
+               elog(ERROR, "DeleteRelationTuple: cache lookup failed for relation %u",
+                        relid);
 
-       /*
-        * delete the relation tuple from pg_class, and finish up.
-        */
+       /* delete the relation tuple from pg_class, and finish up */
        simple_heap_delete(pg_class_desc, &tup->t_self);
-       heap_freetuple(tup);
 
-       heap_close(pg_class_desc, RowExclusiveLock);
-}
+       ReleaseSysCache(tup);
 
-/* --------------------------------
- * RelationTruncateIndexes - This routine is used to truncate all
- * indices associated with the heap relation to zero tuples.
- * The routine will truncate and then reconstruct the indices on
- * the relation specified by the heapId parameter.
- * --------------------------------
- */
-static void
-RelationTruncateIndexes(Oid heapId)
-{
-       Relation        indexRelation;
-       ScanKeyData entry;
-       SysScanDesc     scan;
-       HeapTuple       indexTuple;
-
-       /* Scan pg_index to find indexes on specified heap */
-       indexRelation = heap_openr(IndexRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&entry, 0,
-                                                  Anum_pg_index_indrelid,
-                                                  F_OIDEQ,
-                                                  ObjectIdGetDatum(heapId));
-       scan = systable_beginscan(indexRelation, IndexIndrelidIndex, true,
-                                                         SnapshotNow, 1, &entry);
-
-       while (HeapTupleIsValid(indexTuple = systable_getnext(scan)))
-       {
-               Form_pg_index indexform = (Form_pg_index) GETSTRUCT(indexTuple);
-               Oid                     indexId;
-               IndexInfo  *indexInfo;
-               Relation        heapRelation,
-                                       currentIndex;
-
-               /*
-                * For each index, fetch info needed for index_build
-                */
-               indexId = indexform->indexrelid;
-               indexInfo = BuildIndexInfo(indexform);
-
-               /*
-                * We have to re-open the heap rel each time through this loop
-                * because index_build will close it again.  We need grab no lock,
-                * however, because we assume heap_truncate is holding an
-                * exclusive lock on the heap rel.
-                */
-               heapRelation = heap_open(heapId, NoLock);
-
-               /* Open the index relation */
-               currentIndex = index_open(indexId);
-
-               /* Obtain exclusive lock on it, just to be sure */
-               LockRelation(currentIndex, AccessExclusiveLock);
-
-               /*
-                * Drop any buffers associated with this index. If they're dirty,
-                * they're just dropped without bothering to flush to disk.
-                */
-               DropRelationBuffers(currentIndex);
-
-               /* Now truncate the actual data and set blocks to zero */
-               smgrtruncate(DEFAULT_SMGR, currentIndex, 0);
-               currentIndex->rd_nblocks = 0;
-               currentIndex->rd_targblock = InvalidBlockNumber;
-
-               /* Initialize the index and rebuild */
-               index_build(heapRelation, currentIndex, indexInfo);
-
-               /*
-                * index_build will close both the heap and index relations (but
-                * not give up the locks we hold on them).
-                */
-       }
-
-       /* Complete the scan and close pg_index */
-       systable_endscan(scan);
-       heap_close(indexRelation, AccessShareLock);
+       heap_close(pg_class_desc, RowExclusiveLock);
 }
 
-/* ----------------------------
- *      heap_truncate
+/*
+ *             DeleteAttributeTuples
  *
- *      This routine is used to truncate the data from the
- *      storage manager of any data within the relation handed
- *      to this routine.
- * ----------------------------
+ * Remove pg_attribute rows for the given relid.
+ *
+ * Note: this is shared by relation deletion and index deletion.  It's
+ * not intended for use anyplace else.
  */
-
 void
-heap_truncate(Oid rid)
+DeleteAttributeTuples(Oid relid)
 {
-       Relation        rel;
-
-       /* Open relation for processing, and grab exclusive access on it. */
-
-       rel = heap_open(rid, AccessExclusiveLock);
-
-       /*
-        * TRUNCATE TABLE within a transaction block is dangerous, because if
-        * the transaction is later rolled back we have no way to undo
-        * truncation of the relation's physical file.  Disallow it except for
-        * a rel created in the current xact (which would be deleted on abort,
-        * anyway).
-        */
-       if (IsTransactionBlock() && !rel->rd_myxactonly)
-               elog(ERROR, "TRUNCATE TABLE cannot run inside a transaction block");
-
-       /*
-        * Release any buffers associated with this relation.  If they're
-        * dirty, they're just dropped without bothering to flush to disk.
-        */
-       DropRelationBuffers(rel);
-
-       /* Now truncate the actual data and set blocks to zero */
-       smgrtruncate(DEFAULT_SMGR, rel, 0);
-       rel->rd_nblocks = 0;
-       rel->rd_targblock = InvalidBlockNumber;
-
-       /* If this relation has indexes, truncate the indexes too */
-       RelationTruncateIndexes(rid);
-
-       /*
-        * Close the relation, but keep exclusive lock on it until commit.
-        */
-       heap_close(rel, NoLock);
-}
+       Relation        attrel;
+       SysScanDesc     scan;
+       ScanKeyData key[1];
+       HeapTuple       atttup;
 
+       /* Grab an appropriate lock on the pg_attribute relation */
+       attrel = heap_openr(AttributeRelationName, RowExclusiveLock);
 
-/* --------------------------------
- *             DeleteAttributeTuples
- *
- * --------------------------------
- */
-static void
-DeleteAttributeTuples(Relation rel)
-{
-       Relation        pg_attribute_desc;
-       HeapTuple       tup;
-       int2            attnum;
+       /* Use the index to scan only attributes of the target relation */
+       ScanKeyEntryInitialize(&key[0], 0x0,
+                                                  Anum_pg_attribute_attrelid, F_OIDEQ,
+                                                  ObjectIdGetDatum(relid));
 
-       /*
-        * open pg_attribute
-        */
-       pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
+       scan = systable_beginscan(attrel, AttributeRelidNumIndex, true,
+                                                         SnapshotNow, 1, key);
 
-       for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
-                attnum <= rel->rd_att->natts;
-                attnum++)
+       /* Delete all the matching tuples */
+       while ((atttup = systable_getnext(scan)) != NULL)
        {
-               tup = SearchSysCacheCopy(ATTNUM,
-                                                                ObjectIdGetDatum(RelationGetRelid(rel)),
-                                                                Int16GetDatum(attnum),
-                                                                0, 0);
-               if (HeapTupleIsValid(tup))
-               {
-                       simple_heap_delete(pg_attribute_desc, &tup->t_self);
-                       heap_freetuple(tup);
-               }
+               simple_heap_delete(attrel, &atttup->t_self);
        }
 
-       heap_close(pg_attribute_desc, RowExclusiveLock);
+       /* Clean up after the scan */
+       systable_endscan(scan);
+       heap_close(attrel, RowExclusiveLock);
 }
 
 /* ----------------------------------------------------------------
@@ -1033,14 +910,14 @@ heap_drop_with_catalog(Oid rid)
        /*
         * delete attribute tuples and associated defaults
         */
-       DeleteAttributeTuples(rel);
+       DeleteAttributeTuples(RelationGetRelid(rel));
 
        RemoveDefaults(rel);
 
        /*
         * delete relation tuple
         */
-       DeleteRelationTuple(rel);
+       DeleteRelationTuple(RelationGetRelid(rel));
 
        /*
         * unlink the relation's physical file and finish up.
@@ -1734,3 +1611,127 @@ RemoveStatistics(Relation rel)
        heap_endscan(scan);
        heap_close(pgstatistic, RowExclusiveLock);
 }
+
+
+/*
+ * RelationTruncateIndexes - truncate all
+ * indices associated with the heap relation to zero tuples.
+ *
+ * The routine will truncate and then reconstruct the indices on
+ * the relation specified by the heapId parameter.
+ */
+static void
+RelationTruncateIndexes(Oid heapId)
+{
+       Relation        indexRelation;
+       ScanKeyData entry;
+       SysScanDesc     scan;
+       HeapTuple       indexTuple;
+
+       /* Scan pg_index to find indexes on specified heap */
+       indexRelation = heap_openr(IndexRelationName, AccessShareLock);
+       ScanKeyEntryInitialize(&entry, 0,
+                                                  Anum_pg_index_indrelid,
+                                                  F_OIDEQ,
+                                                  ObjectIdGetDatum(heapId));
+       scan = systable_beginscan(indexRelation, IndexIndrelidIndex, true,
+                                                         SnapshotNow, 1, &entry);
+
+       while (HeapTupleIsValid(indexTuple = systable_getnext(scan)))
+       {
+               Form_pg_index indexform = (Form_pg_index) GETSTRUCT(indexTuple);
+               Oid                     indexId;
+               IndexInfo  *indexInfo;
+               Relation        heapRelation,
+                                       currentIndex;
+
+               /*
+                * For each index, fetch info needed for index_build
+                */
+               indexId = indexform->indexrelid;
+               indexInfo = BuildIndexInfo(indexform);
+
+               /*
+                * We have to re-open the heap rel each time through this loop
+                * because index_build will close it again.  We need grab no lock,
+                * however, because we assume heap_truncate is holding an
+                * exclusive lock on the heap rel.
+                */
+               heapRelation = heap_open(heapId, NoLock);
+
+               /* Open the index relation */
+               currentIndex = index_open(indexId);
+
+               /* Obtain exclusive lock on it, just to be sure */
+               LockRelation(currentIndex, AccessExclusiveLock);
+
+               /*
+                * Drop any buffers associated with this index. If they're dirty,
+                * they're just dropped without bothering to flush to disk.
+                */
+               DropRelationBuffers(currentIndex);
+
+               /* Now truncate the actual data and set blocks to zero */
+               smgrtruncate(DEFAULT_SMGR, currentIndex, 0);
+               currentIndex->rd_nblocks = 0;
+               currentIndex->rd_targblock = InvalidBlockNumber;
+
+               /* Initialize the index and rebuild */
+               index_build(heapRelation, currentIndex, indexInfo);
+
+               /*
+                * index_build will close both the heap and index relations (but
+                * not give up the locks we hold on them).
+                */
+       }
+
+       /* Complete the scan and close pg_index */
+       systable_endscan(scan);
+       heap_close(indexRelation, AccessShareLock);
+}
+
+/*
+ *      heap_truncate
+ *
+ *      This routine is used to truncate the data from the
+ *      storage manager of any data within the relation handed
+ *      to this routine.
+ */
+void
+heap_truncate(Oid rid)
+{
+       Relation        rel;
+
+       /* Open relation for processing, and grab exclusive access on it. */
+
+       rel = heap_open(rid, AccessExclusiveLock);
+
+       /*
+        * TRUNCATE TABLE within a transaction block is dangerous, because if
+        * the transaction is later rolled back we have no way to undo
+        * truncation of the relation's physical file.  Disallow it except for
+        * a rel created in the current xact (which would be deleted on abort,
+        * anyway).
+        */
+       if (IsTransactionBlock() && !rel->rd_myxactonly)
+               elog(ERROR, "TRUNCATE TABLE cannot run inside a transaction block");
+
+       /*
+        * Release any buffers associated with this relation.  If they're
+        * dirty, they're just dropped without bothering to flush to disk.
+        */
+       DropRelationBuffers(rel);
+
+       /* Now truncate the actual data and set blocks to zero */
+       smgrtruncate(DEFAULT_SMGR, rel, 0);
+       rel->rd_nblocks = 0;
+       rel->rd_targblock = InvalidBlockNumber;
+
+       /* If this relation has indexes, truncate the indexes too */
+       RelationTruncateIndexes(rid);
+
+       /*
+        * Close the relation, but keep exclusive lock on it until commit.
+        */
+       heap_close(rel, NoLock);
+}
index 30cef89feff6f7aa17a4bcfbf2198aeed62ffa5c..996fb80a7cbdc3f07eddbc8a3e389f70b3bcb920 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.182 2002/07/12 18:43:13 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.183 2002/07/14 21:08:08 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -789,10 +789,7 @@ index_drop(Oid indexId)
        Relation        userHeapRelation;
        Relation        userIndexRelation;
        Relation        indexRelation;
-       Relation        relationRelation;
-       Relation        attributeRelation;
        HeapTuple       tuple;
-       int16           attnum;
        int                     i;
 
        Assert(OidIsValid(indexId));
@@ -818,53 +815,27 @@ index_drop(Oid indexId)
        /*
         * fix RELATION relation
         */
-       relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
-
-       /* Remove the pg_class tuple for the index itself */
-       tuple = SearchSysCacheCopy(RELOID,
-                                                          ObjectIdGetDatum(indexId),
-                                                          0, 0, 0);
-       if (!HeapTupleIsValid(tuple))
-               elog(ERROR, "index_drop: cache lookup failed for index %u",
-                        indexId);
-
-       simple_heap_delete(relationRelation, &tuple->t_self);
-       heap_freetuple(tuple);
-
-       heap_close(relationRelation, RowExclusiveLock);
-
+       DeleteRelationTuple(indexId);
        /*
         * fix ATTRIBUTE relation
         */
-       attributeRelation = heap_openr(AttributeRelationName, RowExclusiveLock);
-
-       attnum = 1;                                     /* indexes start at 1 */
-
-       while (HeapTupleIsValid(tuple = SearchSysCacheCopy(ATTNUM,
-                                                                                          ObjectIdGetDatum(indexId),
-                                                                                                  Int16GetDatum(attnum),
-                                                                                                          0, 0)))
-       {
-               simple_heap_delete(attributeRelation, &tuple->t_self);
-               heap_freetuple(tuple);
-               attnum++;
-       }
-       heap_close(attributeRelation, RowExclusiveLock);
+       DeleteAttributeTuples(indexId);
 
        /*
         * fix INDEX relation
         */
        indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
 
-       tuple = SearchSysCacheCopy(INDEXRELID,
-                                                          ObjectIdGetDatum(indexId),
-                                                          0, 0, 0);
+       tuple = SearchSysCache(INDEXRELID,
+                                                  ObjectIdGetDatum(indexId),
+                                                  0, 0, 0);
        if (!HeapTupleIsValid(tuple))
                elog(ERROR, "index_drop: cache lookup failed for index %u",
                         indexId);
 
        simple_heap_delete(indexRelation, &tuple->t_self);
-       heap_freetuple(tuple);
+
+       ReleaseSysCache(tuple);
        heap_close(indexRelation, RowExclusiveLock);
 
        /*
index 5cf87e2631f4af9f95822ede4351fec3c8668c1c..44c8e13bf61721aef89ca1a02f1b7eaaa5d3ec0e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: heap.h,v 1.52 2002/07/12 18:43:19 tgl Exp $
+ * $Id: heap.h,v 1.53 2002/07/14 21:08:08 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,6 +61,9 @@ extern Node *cookDefault(ParseState *pstate,
 extern int     RemoveRelConstraints(Relation rel, const char *constrName,
                                                                 DropBehavior behavior);
 
+extern void DeleteRelationTuple(Oid relid);
+extern void DeleteAttributeTuples(Oid relid);
+
 extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
                                                  bool relhasoids);