summaryrefslogtreecommitdiff
path: root/src/backend/catalog/pg_depend.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-07-15 11:41:47 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-07-15 11:41:47 -0400
commita49d081235997c67e8aab7a523b17e8d1cb93184 (patch)
tree4bf81347757488fc1ab5c651dc4f3ab0eb1b8a87 /src/backend/catalog/pg_depend.c
parente529b2dc37ac80ccebd76cdbb14966d3b40819c9 (diff)
downloadpostgresql-a49d081235997c67e8aab7a523b17e8d1cb93184.tar.gz
Replace explicit PIN entries in pg_depend with an OID range test.
As of v14, pg_depend contains almost 7000 "pin" entries recording the OIDs of built-in objects. This is a fair amount of bloat for every database, and it adds time to pg_depend lookups as well as initdb. We can get rid of all of those entries in favor of an OID range check, i.e. "OIDs below FirstUnpinnedObjectId are pinned". (template1 and the public schema are exceptions. Those exceptions are now wired into IsPinnedObject() instead of initdb's code for filling pg_depend, but it's the same amount of cruft either way.) The contents of pg_shdepend are modified likewise. Discussion: https://postgr.es/m/3737988.1618451008@sss.pgh.pa.us
Diffstat (limited to 'src/backend/catalog/pg_depend.c')
-rw-r--r--src/backend/catalog/pg_depend.c66
1 files changed, 16 insertions, 50 deletions
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 54688094f5..10f3119670 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -17,6 +17,7 @@
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
+#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/pg_constraint.h"
@@ -29,7 +30,7 @@
#include "utils/rel.h"
-static bool isObjectPinned(const ObjectAddress *object, Relation rel);
+static bool isObjectPinned(const ObjectAddress *object);
/*
@@ -69,8 +70,11 @@ recordMultipleDependencies(const ObjectAddress *depender,
return; /* nothing to do */
/*
- * During bootstrap, do nothing since pg_depend may not exist yet. initdb
- * will fill in appropriate pg_depend entries after bootstrap.
+ * During bootstrap, do nothing since pg_depend may not exist yet.
+ *
+ * Objects created during bootstrap are most likely pinned, and the few
+ * that are not do not have dependencies on each other, so that there
+ * would be no need to make a pg_depend entry anyway.
*/
if (IsBootstrapProcessingMode())
return;
@@ -99,7 +103,7 @@ recordMultipleDependencies(const ObjectAddress *depender,
* need to record dependencies on it. This saves lots of space in
* pg_depend, so it's worth the time taken to check.
*/
- if (isObjectPinned(referenced, dependDesc))
+ if (isObjectPinned(referenced))
continue;
if (slot_init_count < max_slots)
@@ -399,8 +403,6 @@ changeDependencyFor(Oid classId, Oid objectId,
bool oldIsPinned;
bool newIsPinned;
- depRel = table_open(DependRelationId, RowExclusiveLock);
-
/*
* Check to see if either oldRefObjectId or newRefObjectId is pinned.
* Pinned objects should not have any dependency entries pointing to them,
@@ -411,16 +413,14 @@ changeDependencyFor(Oid classId, Oid objectId,
objAddr.objectId = oldRefObjectId;
objAddr.objectSubId = 0;
- oldIsPinned = isObjectPinned(&objAddr, depRel);
+ oldIsPinned = isObjectPinned(&objAddr);
objAddr.objectId = newRefObjectId;
- newIsPinned = isObjectPinned(&objAddr, depRel);
+ newIsPinned = isObjectPinned(&objAddr);
if (oldIsPinned)
{
- table_close(depRel, RowExclusiveLock);
-
/*
* If both are pinned, we need do nothing. However, return 1 not 0,
* else callers will think this is an error case.
@@ -440,6 +440,8 @@ changeDependencyFor(Oid classId, Oid objectId,
return 1;
}
+ depRel = table_open(DependRelationId, RowExclusiveLock);
+
/* There should be existing dependency record(s), so search. */
ScanKeyInit(&key[0],
Anum_pg_depend_classid,
@@ -574,7 +576,7 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
objAddr.objectId = oldRefObjectId;
objAddr.objectSubId = 0;
- if (isObjectPinned(&objAddr, depRel))
+ if (isObjectPinned(&objAddr))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot remove dependency on %s because it is a system object",
@@ -586,7 +588,7 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
*/
objAddr.objectId = newRefObjectId;
- newIsPinned = isObjectPinned(&objAddr, depRel);
+ newIsPinned = isObjectPinned(&objAddr);
/* Now search for dependency records */
ScanKeyInit(&key[0],
@@ -634,50 +636,14 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId,
* isObjectPinned()
*
* Test if an object is required for basic database functionality.
- * Caller must already have opened pg_depend.
*
* The passed subId, if any, is ignored; we assume that only whole objects
* are pinned (and that this implies pinning their components).
*/
static bool
-isObjectPinned(const ObjectAddress *object, Relation rel)
+isObjectPinned(const ObjectAddress *object)
{
- bool ret = false;
- SysScanDesc scan;
- HeapTuple tup;
- ScanKeyData key[2];
-
- ScanKeyInit(&key[0],
- Anum_pg_depend_refclassid,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(object->classId));
-
- ScanKeyInit(&key[1],
- Anum_pg_depend_refobjid,
- BTEqualStrategyNumber, F_OIDEQ,
- ObjectIdGetDatum(object->objectId));
-
- scan = systable_beginscan(rel, DependReferenceIndexId, true,
- NULL, 2, key);
-
- /*
- * Since we won't generate additional pg_depend entries for pinned
- * objects, there can be at most one entry referencing a pinned object.
- * Hence, it's sufficient to look at the first returned tuple; we don't
- * need to loop.
- */
- tup = systable_getnext(scan);
- if (HeapTupleIsValid(tup))
- {
- Form_pg_depend foundDep = (Form_pg_depend) GETSTRUCT(tup);
-
- if (foundDep->deptype == DEPENDENCY_PIN)
- ret = true;
- }
-
- systable_endscan(scan);
-
- return ret;
+ return IsPinnedObject(object->classId, object->objectId);
}