Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 540e69a

Browse files
committed
Add an index on pg_inherits.inhparent, and use it to avoid seqscans in
find_inheritance_children(). This is a complete no-op in databases without any inheritance. In databases where there are just a few entries in pg_inherits, it could conceivably be a small loss. However, in databases with many inheritance parents, it can be a big win.
1 parent 649b5ec commit 540e69a

File tree

4 files changed

+82
-27
lines changed

4 files changed

+82
-27
lines changed

src/backend/catalog/pg_inherits.c

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313
*
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.3 2009/06/11 14:48:55 momjian Exp $
16+
* $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.4 2009/12/29 22:00:12 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
2020
#include "postgres.h"
2121

22+
#include "access/genam.h"
2223
#include "access/heapam.h"
24+
#include "catalog/indexing.h"
2325
#include "catalog/pg_class.h"
2426
#include "catalog/pg_inherits.h"
2527
#include "catalog/pg_inherits_fn.h"
@@ -29,6 +31,8 @@
2931
#include "utils/syscache.h"
3032
#include "utils/tqual.h"
3133

34+
static int oid_cmp(const void *p1, const void *p2);
35+
3236

3337
/*
3438
* find_inheritance_children
@@ -46,10 +50,14 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
4650
{
4751
List *list = NIL;
4852
Relation relation;
49-
HeapScanDesc scan;
53+
SysScanDesc scan;
5054
ScanKeyData key[1];
5155
HeapTuple inheritsTuple;
5256
Oid inhrelid;
57+
Oid *oidarr;
58+
int maxoids,
59+
numoids,
60+
i;
5361

5462
/*
5563
* Can skip the scan if pg_class shows the relation has never had a
@@ -59,21 +67,52 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
5967
return NIL;
6068

6169
/*
62-
* XXX might be a good idea to create an index on pg_inherits' inhparent
63-
* field, so that we can use an indexscan instead of sequential scan here.
64-
* However, in typical databases pg_inherits won't have enough entries to
65-
* justify an indexscan...
70+
* Scan pg_inherits and build a working array of subclass OIDs.
6671
*/
72+
maxoids = 32;
73+
oidarr = (Oid *) palloc(maxoids * sizeof(Oid));
74+
numoids = 0;
75+
6776
relation = heap_open(InheritsRelationId, AccessShareLock);
77+
6878
ScanKeyInit(&key[0],
6979
Anum_pg_inherits_inhparent,
7080
BTEqualStrategyNumber, F_OIDEQ,
7181
ObjectIdGetDatum(parentrelId));
72-
scan = heap_beginscan(relation, SnapshotNow, 1, key);
7382

74-
while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
83+
scan = systable_beginscan(relation, InheritsParentIndexId, true,
84+
SnapshotNow, 1, key);
85+
86+
while ((inheritsTuple = systable_getnext(scan)) != NULL)
7587
{
7688
inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;
89+
if (numoids >= maxoids)
90+
{
91+
maxoids *= 2;
92+
oidarr = (Oid *) repalloc(oidarr, maxoids * sizeof(Oid));
93+
}
94+
oidarr[numoids++] = inhrelid;
95+
}
96+
97+
systable_endscan(scan);
98+
99+
heap_close(relation, AccessShareLock);
100+
101+
/*
102+
* If we found more than one child, sort them by OID. This ensures
103+
* reasonably consistent behavior regardless of the vagaries of an
104+
* indexscan. This is important since we need to be sure all backends
105+
* lock children in the same order to avoid needless deadlocks.
106+
*/
107+
if (numoids > 1)
108+
qsort(oidarr, numoids, sizeof(Oid), oid_cmp);
109+
110+
/*
111+
* Acquire locks and build the result list.
112+
*/
113+
for (i = 0; i < numoids; i++)
114+
{
115+
inhrelid = oidarr[i];
77116

78117
if (lockmode != NoLock)
79118
{
@@ -99,8 +138,7 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
99138
list = lappend_oid(list, inhrelid);
100139
}
101140

102-
heap_endscan(scan);
103-
heap_close(relation, AccessShareLock);
141+
pfree(oidarr);
104142

105143
return list;
106144
}
@@ -231,7 +269,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
231269
{
232270
Oid this_relid = lfirst_oid(queue_item);
233271
ScanKeyData skey;
234-
HeapScanDesc inhscan;
272+
SysScanDesc inhscan;
235273
HeapTuple inhtup;
236274

237275
/*
@@ -255,9 +293,10 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
255293
BTEqualStrategyNumber, F_OIDEQ,
256294
ObjectIdGetDatum(this_relid));
257295

258-
inhscan = heap_beginscan(inhrel, SnapshotNow, 1, &skey);
296+
inhscan = systable_beginscan(inhrel, InheritsRelidSeqnoIndexId, true,
297+
SnapshotNow, 1, &skey);
259298

260-
while ((inhtup = heap_getnext(inhscan, ForwardScanDirection)) != NULL)
299+
while ((inhtup = systable_getnext(inhscan)) != NULL)
261300
{
262301
Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inhtup);
263302
Oid inhparent = inh->inhparent;
@@ -273,7 +312,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
273312
queue = lappend_oid(queue, inhparent);
274313
}
275314

276-
heap_endscan(inhscan);
315+
systable_endscan(inhscan);
277316

278317
if (result)
279318
break;
@@ -287,3 +326,18 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
287326

288327
return result;
289328
}
329+
330+
331+
/* qsort comparison function */
332+
static int
333+
oid_cmp(const void *p1, const void *p2)
334+
{
335+
Oid v1 = *((const Oid *) p1);
336+
Oid v2 = *((const Oid *) p2);
337+
338+
if (v1 < v2)
339+
return -1;
340+
if (v1 > v2)
341+
return 1;
342+
return 0;
343+
}

src/backend/commands/tablecmds.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.311 2009/12/23 16:43:43 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.312 2009/12/29 22:00:12 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1793,24 +1793,22 @@ StoreCatalogInheritance1(Oid relationId, Oid parentOid,
17931793
int16 seqNumber, Relation inhRelation)
17941794
{
17951795
TupleDesc desc = RelationGetDescr(inhRelation);
1796-
Datum datum[Natts_pg_inherits];
1797-
bool nullarr[Natts_pg_inherits];
1796+
Datum values[Natts_pg_inherits];
1797+
bool nulls[Natts_pg_inherits];
17981798
ObjectAddress childobject,
17991799
parentobject;
18001800
HeapTuple tuple;
18011801

18021802
/*
18031803
* Make the pg_inherits entry
18041804
*/
1805-
datum[0] = ObjectIdGetDatum(relationId); /* inhrelid */
1806-
datum[1] = ObjectIdGetDatum(parentOid); /* inhparent */
1807-
datum[2] = Int16GetDatum(seqNumber); /* inhseqno */
1805+
values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId);
1806+
values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid);
1807+
values[Anum_pg_inherits_inhseqno - 1] = Int16GetDatum(seqNumber);
18081808

1809-
nullarr[0] = false;
1810-
nullarr[1] = false;
1811-
nullarr[2] = false;
1809+
memset(nulls, 0, sizeof(nulls));
18121810

1813-
tuple = heap_form_tuple(desc, datum, nullarr);
1811+
tuple = heap_form_tuple(desc, values, nulls);
18141812

18151813
simple_heap_insert(inhRelation, tuple);
18161814

src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.562 2009/12/29 20:11:45 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.563 2009/12/29 22:00:14 tgl Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 200912281
56+
#define CATALOG_VERSION_NO 200912291
5757

5858
#endif

src/include/catalog/indexing.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.112 2009/12/29 20:11:45 tgl Exp $
11+
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.113 2009/12/29 22:00:14 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -156,6 +156,9 @@ DECLARE_UNIQUE_INDEX(pg_index_indexrelid_index, 2679, on pg_index using btree(in
156156

157157
DECLARE_UNIQUE_INDEX(pg_inherits_relid_seqno_index, 2680, on pg_inherits using btree(inhrelid oid_ops, inhseqno int4_ops));
158158
#define InheritsRelidSeqnoIndexId 2680
159+
/* This following index is not used for a cache and is not unique */
160+
DECLARE_INDEX(pg_inherits_parent_index, 2187, on pg_inherits using btree(inhparent oid_ops));
161+
#define InheritsParentIndexId 2187
159162

160163
DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, on pg_language using btree(lanname name_ops));
161164
#define LanguageNameIndexId 2681

0 commit comments

Comments
 (0)