In DeleteAttributeTuples, use a single indexscan instead of the multiple
authorTom Lane
Sun, 14 Jul 2002 21:08:08 +0000 (21:08 +0000)
committerTom Lane
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);