Skip to content

Commit d03a933

Browse files
committed
Fix performance problems with pg_index lookups (see, for example,
discussion of 5/19/00). pg_index is now searched for indexes of a relation using an indexscan. Moreover, this is done once and cached in the relcache entry for the relation, in the form of a list of OIDs for the indexes. This list is used by the parser and executor to drive lookups in the pg_index syscache when they want to know the properties of the indexes. Net result: index information will be fully cached for repetitive operations such as inserts.
1 parent 9cf80f2 commit d03a933

File tree

13 files changed

+384
-520
lines changed

13 files changed

+384
-520
lines changed

src/backend/catalog/index.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.116 2000/06/17 04:56:36 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.117 2000/06/17 21:48:39 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1105,6 +1105,7 @@ index_create(char *heapRelationName,
11051105
void
11061106
index_drop(Oid indexId)
11071107
{
1108+
Oid heapId;
11081109
Relation userHeapRelation;
11091110
Relation userIndexRelation;
11101111
Relation indexRelation;
@@ -1125,8 +1126,8 @@ index_drop(Oid indexId)
11251126
* else other backends will still see this index in pg_index.
11261127
* ----------------
11271128
*/
1128-
userHeapRelation = heap_open(IndexGetRelation(indexId),
1129-
AccessExclusiveLock);
1129+
heapId = IndexGetRelation(indexId);
1130+
userHeapRelation = heap_open(heapId, AccessExclusiveLock);
11301131

11311132
userIndexRelation = index_open(indexId);
11321133
LockRelation(userIndexRelation, AccessExclusiveLock);
@@ -1158,6 +1159,7 @@ index_drop(Oid indexId)
11581159
*/
11591160
relationRelation = heap_openr(RelationRelationName, RowExclusiveLock);
11601161

1162+
/* Remove the pg_class tuple for the index itself */
11611163
tuple = SearchSysCacheTupleCopy(RELOID,
11621164
ObjectIdGetDatum(indexId),
11631165
0, 0, 0);
@@ -1166,6 +1168,23 @@ index_drop(Oid indexId)
11661168

11671169
heap_delete(relationRelation, &tuple->t_self, NULL);
11681170
heap_freetuple(tuple);
1171+
1172+
/*
1173+
* Find the pg_class tuple for the owning relation. We do not attempt
1174+
* to clear relhasindex, since we are too lazy to test whether any other
1175+
* indexes remain (the next VACUUM will fix it if necessary). But we
1176+
* must send out a shared-cache-inval notice on the owning relation
1177+
* to ensure other backends update their relcache lists of indexes.
1178+
*/
1179+
tuple = SearchSysCacheTupleCopy(RELOID,
1180+
ObjectIdGetDatum(heapId),
1181+
0, 0, 0);
1182+
1183+
Assert(HeapTupleIsValid(tuple));
1184+
1185+
ImmediateInvalidateSharedHeapTuple(relationRelation, tuple);
1186+
heap_freetuple(tuple);
1187+
11691188
heap_close(relationRelation, RowExclusiveLock);
11701189

11711190
/* ----------------
@@ -1447,9 +1466,6 @@ setRelhasindexInplace(Oid relid, bool hasindex, bool immediate)
14471466
*/
14481467
if (pg_class_scan)
14491468
{
1450-
1451-
if (!IsBootstrapProcessingMode())
1452-
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
14531469
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
14541470
rd_rel->relhasindex = hasindex;
14551471
WriteNoReleaseBuffer(pg_class_scan->rs_cbuf);
@@ -1461,12 +1477,18 @@ setRelhasindexInplace(Oid relid, bool hasindex, bool immediate)
14611477

14621478
htup.t_self = tuple->t_self;
14631479
heap_fetch(pg_class, SnapshotNow, &htup, &buffer);
1464-
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
14651480
rd_rel = (Form_pg_class) GETSTRUCT(&htup);
14661481
rd_rel->relhasindex = hasindex;
14671482
WriteBuffer(buffer);
14681483
}
14691484

1485+
/*
1486+
* Send out a shared-cache-inval message so other backends notice the
1487+
* update and fix their syscaches/relcaches.
1488+
*/
1489+
if (!IsBootstrapProcessingMode())
1490+
ImmediateInvalidateSharedHeapTuple(pg_class, tuple);
1491+
14701492
if (!pg_class_scan)
14711493
heap_freetuple(tuple);
14721494
else

src/backend/commands/copy.c

Lines changed: 24 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.114 2000/06/15 03:32:07 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.115 2000/06/17 21:48:42 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -32,6 +32,7 @@
3232
#include "tcop/tcopprot.h"
3333
#include "utils/acl.h"
3434
#include "utils/builtins.h"
35+
#include "utils/relcache.h"
3536
#include "utils/syscache.h"
3637

3738
#ifdef MULTIBYTE
@@ -1081,78 +1082,43 @@ IsTypeByVal(Oid type)
10811082
* Space for the array itself is palloc'ed.
10821083
*/
10831084

1084-
typedef struct rel_list
1085-
{
1086-
Oid index_rel_oid;
1087-
struct rel_list *next;
1088-
} RelationList;
1089-
10901085
static void
10911086
GetIndexRelations(Oid main_relation_oid,
10921087
int *n_indices,
10931088
Relation **index_rels)
10941089
{
1095-
RelationList *head,
1096-
*scan;
1097-
Relation pg_index_rel;
1098-
HeapScanDesc scandesc;
1099-
Oid index_relation_oid;
1100-
HeapTuple tuple;
1101-
TupleDesc tupDesc;
1090+
Relation relation;
1091+
List *indexoidlist,
1092+
*indexoidscan;
11021093
int i;
1103-
bool isnull;
11041094

1105-
pg_index_rel = heap_openr(IndexRelationName, AccessShareLock);
1106-
scandesc = heap_beginscan(pg_index_rel, 0, SnapshotNow, 0, NULL);
1107-
tupDesc = RelationGetDescr(pg_index_rel);
1095+
relation = heap_open(main_relation_oid, AccessShareLock);
1096+
indexoidlist = RelationGetIndexList(relation);
11081097

1109-
*n_indices = 0;
1098+
*n_indices = length(indexoidlist);
11101099

1111-
head = (RelationList *) palloc(sizeof(RelationList));
1112-
scan = head;
1113-
head->next = NULL;
1100+
if (*n_indices > 0)
1101+
*index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
1102+
else
1103+
*index_rels = NULL;
11141104

1115-
while (HeapTupleIsValid(tuple = heap_getnext(scandesc, 0)))
1105+
i = 0;
1106+
foreach(indexoidscan, indexoidlist)
11161107
{
1108+
Oid indexoid = lfirsti(indexoidscan);
1109+
Relation index = index_open(indexoid);
11171110

1118-
index_relation_oid = (Oid) DatumGetInt32(heap_getattr(tuple, 2,
1119-
tupDesc, &isnull));
1120-
if (index_relation_oid == main_relation_oid)
1121-
{
1122-
scan->index_rel_oid = (Oid) DatumGetInt32(heap_getattr(tuple,
1123-
Anum_pg_index_indexrelid,
1124-
tupDesc, &isnull));
1125-
(*n_indices)++;
1126-
scan->next = (RelationList *) palloc(sizeof(RelationList));
1127-
scan = scan->next;
1128-
}
1129-
}
1130-
1131-
heap_endscan(scandesc);
1132-
heap_close(pg_index_rel, AccessShareLock);
1133-
1134-
/* We cannot trust to relhasindex of the main_relation now, so... */
1135-
if (*n_indices == 0)
1136-
return;
1137-
1138-
*index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
1139-
1140-
for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
1141-
{
1142-
(*index_rels)[i] = index_open(scan->index_rel_oid);
11431111
/* see comments in ExecOpenIndices() in execUtils.c */
1144-
if ((*index_rels)[i] != NULL &&
1145-
((*index_rels)[i])->rd_rel->relam != BTREE_AM_OID &&
1146-
((*index_rels)[i])->rd_rel->relam != HASH_AM_OID)
1147-
LockRelation((*index_rels)[i], AccessExclusiveLock);
1112+
if (index != NULL &&
1113+
index->rd_rel->relam != BTREE_AM_OID &&
1114+
index->rd_rel->relam != HASH_AM_OID)
1115+
LockRelation(index, AccessExclusiveLock);
1116+
(*index_rels)[i] = index;
1117+
i++;
11481118
}
11491119

1150-
for (i = 0, scan = head; i < *n_indices + 1; i++)
1151-
{
1152-
scan = head->next;
1153-
pfree(head);
1154-
head = scan;
1155-
}
1120+
freeList(indexoidlist);
1121+
heap_close(relation, AccessShareLock);
11561122
}
11571123

11581124
/*

src/backend/commands/indexcmds.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.29 2000/06/15 03:32:07 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.30 2000/06/17 21:48:42 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -221,6 +221,13 @@ DefineIndex(char *heapRelationName,
221221
lossy, unique, primary);
222222
}
223223

224+
/*
225+
* We update the relation's pg_class tuple even if it already has
226+
* relhasindex = true. This is needed to cause a shared-cache-inval
227+
* message to be sent for the pg_class tuple, which will cause other
228+
* backends to flush their relcache entries and in particular their
229+
* cached lists of the indexes for this relation.
230+
*/
224231
setRelhasindexInplace(relationId, true, false);
225232
}
226233

src/backend/commands/vacuum.c

Lines changed: 20 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.159 2000/05/29 17:40:43 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.160 2000/06/17 21:48:43 tgl Exp $
1212
*
1313
1414
*-------------------------------------------------------------------------
@@ -72,7 +72,7 @@ static void update_relstats(Oid relid, int num_pages, int num_tuples, bool hasin
7272
static VacPage tid_reaped(ItemPointer itemptr, VacPageList vacpagelist);
7373
static void reap_page(VacPageList vacpagelist, VacPage vacpage);
7474
static void vpage_insert(VacPageList vacpagelist, VacPage vpnew);
75-
static void get_indices(Oid relid, int *nindices, Relation **Irel);
75+
static void get_indices(Relation relation, int *nindices, Relation **Irel);
7676
static void close_indices(int nindices, Relation *Irel);
7777
static void get_index_desc(Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc);
7878
static void *vac_find_eq(void *bot, int nelem, int size, void *elm,
@@ -416,7 +416,7 @@ vacuum_rel(Oid relid, bool analyze)
416416
/* Now open indices */
417417
nindices = 0;
418418
Irel = (Relation *) NULL;
419-
get_indices(vacrelstats->relid, &nindices, &Irel);
419+
get_indices(onerel, &nindices, &Irel);
420420
if (!Irel)
421421
reindex = false;
422422
else if (!RelationGetForm(onerel)->relhasindex)
@@ -2331,80 +2331,33 @@ CommonSpecialPortalIsOpen(void)
23312331
return CommonSpecialPortalInUse;
23322332
}
23332333

2334+
23342335
static void
2335-
get_indices(Oid relid, int *nindices, Relation **Irel)
2336+
get_indices(Relation relation, int *nindices, Relation **Irel)
23362337
{
2337-
Relation pgindex;
2338-
Relation irel;
2339-
TupleDesc tupdesc;
2340-
HeapTuple tuple;
2341-
HeapScanDesc scan;
2342-
Datum d;
2343-
int i,
2344-
k;
2345-
bool n;
2346-
ScanKeyData key;
2347-
Oid *ioid;
2348-
2349-
*nindices = i = 0;
2350-
2351-
ioid = (Oid *) palloc(10 * sizeof(Oid));
2352-
2353-
/* prepare a heap scan on the pg_index relation */
2354-
pgindex = heap_openr(IndexRelationName, AccessShareLock);
2355-
tupdesc = RelationGetDescr(pgindex);
2356-
2357-
ScanKeyEntryInitialize(&key, 0x0, Anum_pg_index_indrelid,
2358-
F_OIDEQ,
2359-
ObjectIdGetDatum(relid));
2360-
2361-
scan = heap_beginscan(pgindex, false, SnapshotNow, 1, &key);
2362-
2363-
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
2364-
{
2365-
d = heap_getattr(tuple, Anum_pg_index_indexrelid,
2366-
tupdesc, &n);
2367-
i++;
2368-
if (i % 10 == 0)
2369-
ioid = (Oid *) repalloc(ioid, (i + 10) * sizeof(Oid));
2370-
ioid[i - 1] = DatumGetObjectId(d);
2371-
}
2338+
List *indexoidlist,
2339+
*indexoidscan;
2340+
int i;
23722341

2373-
heap_endscan(scan);
2374-
heap_close(pgindex, AccessShareLock);
2342+
indexoidlist = RelationGetIndexList(relation);
23752343

2376-
if (i == 0)
2377-
{ /* No one index found */
2378-
pfree(ioid);
2379-
return;
2380-
}
2344+
*nindices = length(indexoidlist);
23812345

2382-
if (Irel != (Relation **) NULL)
2383-
*Irel = (Relation *) palloc(i * sizeof(Relation));
2346+
if (*nindices > 0)
2347+
*Irel = (Relation *) palloc(*nindices * sizeof(Relation));
2348+
else
2349+
*Irel = NULL;
23842350

2385-
for (k = 0; i > 0;)
2351+
i = 0;
2352+
foreach(indexoidscan, indexoidlist)
23862353
{
2387-
irel = index_open(ioid[--i]);
2388-
if (irel != (Relation) NULL)
2389-
{
2390-
if (Irel != (Relation **) NULL)
2391-
(*Irel)[k] = irel;
2392-
else
2393-
index_close(irel);
2394-
k++;
2395-
}
2396-
else
2397-
elog(NOTICE, "CAN'T OPEN INDEX %u - SKIP IT", ioid[i]);
2398-
}
2399-
*nindices = k;
2400-
pfree(ioid);
2354+
Oid indexoid = lfirsti(indexoidscan);
24012355

2402-
if (Irel != (Relation **) NULL && *nindices == 0)
2403-
{
2404-
pfree(*Irel);
2405-
*Irel = (Relation *) NULL;
2356+
(*Irel)[i] = index_open(indexoid);
2357+
i++;
24062358
}
24072359

2360+
freeList(indexoidlist);
24082361
}
24092362

24102363

src/backend/executor/execMain.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*
2828
*
2929
* IDENTIFICATION
30-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.117 2000/06/15 04:09:50 momjian Exp $
30+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.118 2000/06/17 21:48:47 tgl Exp $
3131
*
3232
*-------------------------------------------------------------------------
3333
*/
@@ -735,7 +735,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
735735
*/
736736
if (resultRelationDesc->rd_rel->relhasindex &&
737737
operation != CMD_DELETE)
738-
ExecOpenIndices(resultRelationOid, resultRelationInfo);
738+
ExecOpenIndices(resultRelationInfo);
739739

740740
estate->es_result_relation_info = resultRelationInfo;
741741
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy