Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7863404

Browse files
committed
A bunch of changes aimed at reducing backend startup time...
Improve 'pg_internal.init' relcache entry preload mechanism so that it issafe to use for all system catalogs, and arrange to preload a realisticset of system-catalog entries instead of only the three nailed-in-cacheindexes that were formerly loaded this way. Fix mechanism for deletingout-of-date pg_internal.init files: this must be synchronized with transactioncommit, not just done at random times within transactions. Drive it offrelcache invalidation mechanism so that no special-case tests are needed.Cache additional information in relcache entries for indexes (their pg_indextuples and index-operator OIDs) to eliminate repeated lookups. Also cacheindex opclass info at the per-opclass level to avoid repeated lookups duringrelcache load.Generalize 'systable scan' utilities originally developed by Hiroshi,move them into genam.c, use in a number of places where there was formerlyugly code for choosing either heap or index scan. In particular this allowssimplification of the logic that prevents infinite recursion between syscacheand relcache during startup: we can easily switch to heapscans in relcache.cwhen and where needed to avoid recursion, so IndexScanOK becomes simpler anddoes not need any expensive initialization.Eliminate useless opening of a heapscan data structure while doing an indexscan(this saves an mdnblocks call and thus at least one kernel call).
1 parent8e2998d commit7863404

File tree

33 files changed

+1963
-2186
lines changed

33 files changed

+1963
-2186
lines changed

‎src/backend/access/index/genam.c

Lines changed: 158 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.30 2001/10/28 06:25:41 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.31 2002/02/19 20:11:10 tgl Exp $
1212
*
1313
* NOTES
1414
* many of the old access method routines have been turned into
@@ -44,12 +44,14 @@
4444
*next item pointer using the flags.
4545
* ----------------------------------------------------------------
4646
*/
47-
4847
#include"postgres.h"
49-
#include"access/genam.h"
5048

49+
#include"access/genam.h"
50+
#include"access/heapam.h"
51+
#include"miscadmin.h"
5152
#include"pgstat.h"
5253

54+
5355
/* ----------------------------------------------------------------
5456
*general access method routines
5557
*
@@ -242,3 +244,156 @@ IndexScanRestorePosition(IndexScanDesc scan)
242244
}
243245

244246
#endif
247+
248+
249+
/* ----------------------------------------------------------------
250+
*heap-or-index-scan access to system catalogs
251+
*
252+
*These functions support system catalog accesses that normally use
253+
*an index but need to be capable of being switched to heap scans
254+
*if the system indexes are unavailable. The interface is
255+
*as easy to use as a heap scan, and hides all the extra cruft of
256+
*the present indexscan API.
257+
*
258+
*The specified scan keys must be compatible with the named index.
259+
*Generally this means that they must constrain either all columns
260+
*of the index, or the first K columns of an N-column index.
261+
*
262+
*These routines would work fine with non-system tables, actually,
263+
*but they're only useful when there is a known index to use with
264+
*the given scan keys, so in practice they're only good for
265+
*predetermined types of scans of system catalogs.
266+
* ----------------------------------------------------------------
267+
*/
268+
269+
/*
270+
* systable_beginscan --- set up for heap-or-index scan
271+
*
272+
*rel: catalog to scan, already opened and suitably locked
273+
*indexRelname: name of index to conditionally use
274+
*indexOK: if false, forces a heap scan (see notes below)
275+
*snapshot: time qual to use (usually should be SnapshotNow)
276+
*nkeys, key: scan keys
277+
*
278+
* The attribute numbers in the scan key should be set for the heap case.
279+
* If we choose to index, we reset them to 1..n to reference the index
280+
* columns. Note this means there must be one scankey qualification per
281+
* index column! This is checked by the Asserts in the normal, index-using
282+
* case, but won't be checked if the heapscan path is taken.
283+
*
284+
* The routine checks the normal cases for whether an indexscan is safe,
285+
* but caller can make additional checks and pass indexOK=false if needed.
286+
* In standard case indexOK can simply be constant TRUE.
287+
*/
288+
SysScanDesc
289+
systable_beginscan(Relationrel,
290+
constchar*indexRelname,
291+
boolindexOK,
292+
Snapshotsnapshot,
293+
unsignednkeys,ScanKeykey)
294+
{
295+
SysScanDescsysscan;
296+
297+
sysscan= (SysScanDesc)palloc(sizeof(SysScanDescData));
298+
sysscan->heap_rel=rel;
299+
sysscan->snapshot=snapshot;
300+
sysscan->tuple.t_datamcxt=NULL;
301+
sysscan->tuple.t_data=NULL;
302+
sysscan->buffer=InvalidBuffer;
303+
304+
if (indexOK&&
305+
rel->rd_rel->relhasindex&&
306+
!IsIgnoringSystemIndexes())
307+
{
308+
Relationirel;
309+
unsignedi;
310+
311+
sysscan->irel=irel=index_openr(indexRelname);
312+
/*
313+
* Change attribute numbers to be index column numbers.
314+
*
315+
* This code could be generalized to search for the index key numbers
316+
* to substitute, but for now there's no need.
317+
*/
318+
for (i=0;i<nkeys;i++)
319+
{
320+
Assert(key[i].sk_attno==irel->rd_index->indkey[i]);
321+
key[i].sk_attno=i+1;
322+
}
323+
sysscan->iscan=index_beginscan(irel, false,nkeys,key);
324+
sysscan->scan=NULL;
325+
}
326+
else
327+
{
328+
sysscan->irel= (Relation)NULL;
329+
sysscan->scan=heap_beginscan(rel, false,snapshot,nkeys,key);
330+
sysscan->iscan=NULL;
331+
}
332+
333+
returnsysscan;
334+
}
335+
336+
/*
337+
* systable_getnext --- get next tuple in a heap-or-index scan
338+
*
339+
* Returns NULL if no more tuples available.
340+
*
341+
* Note that returned tuple is a reference to data in a disk buffer;
342+
* it must not be modified, and should be presumed inaccessible after
343+
* next getnext() or endscan() call.
344+
*/
345+
HeapTuple
346+
systable_getnext(SysScanDescsysscan)
347+
{
348+
HeapTuplehtup= (HeapTuple)NULL;
349+
350+
if (sysscan->irel)
351+
{
352+
RetrieveIndexResultindexRes;
353+
354+
if (BufferIsValid(sysscan->buffer))
355+
{
356+
ReleaseBuffer(sysscan->buffer);
357+
sysscan->buffer=InvalidBuffer;
358+
}
359+
360+
while ((indexRes=index_getnext(sysscan->iscan,ForwardScanDirection))!=NULL)
361+
{
362+
sysscan->tuple.t_self=indexRes->heap_iptr;
363+
pfree(indexRes);
364+
heap_fetch(sysscan->heap_rel,sysscan->snapshot,
365+
&sysscan->tuple,&sysscan->buffer,
366+
sysscan->iscan);
367+
if (sysscan->tuple.t_data!=NULL)
368+
{
369+
htup=&sysscan->tuple;
370+
break;
371+
}
372+
}
373+
}
374+
else
375+
htup=heap_getnext(sysscan->scan,0);
376+
377+
returnhtup;
378+
}
379+
380+
/*
381+
* systable_endscan --- close scan, release resources
382+
*
383+
* Note that it's still up to the caller to close the heap relation.
384+
*/
385+
void
386+
systable_endscan(SysScanDescsysscan)
387+
{
388+
if (sysscan->irel)
389+
{
390+
if (BufferIsValid(sysscan->buffer))
391+
ReleaseBuffer(sysscan->buffer);
392+
index_endscan(sysscan->iscan);
393+
index_close(sysscan->irel);
394+
}
395+
else
396+
heap_endscan(sysscan->scan);
397+
398+
pfree(sysscan);
399+
}

‎src/backend/access/index/istrat.c

Lines changed: 3 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,19 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.56 2001/11/05 17:46:24 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.57 2002/02/19 20:11:10 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
1616
#include"postgres.h"
1717

18-
#include"access/heapam.h"
1918
#include"access/istrat.h"
20-
#include"catalog/catname.h"
21-
#include"catalog/pg_amop.h"
22-
#include"catalog/pg_amproc.h"
23-
#include"catalog/pg_index.h"
24-
#include"catalog/pg_operator.h"
25-
#include"miscadmin.h"
26-
#include"utils/fmgroids.h"
27-
#include"utils/syscache.h"
19+
2820

2921
#ifdefUSE_ASSERT_CHECKING
3022
staticboolStrategyEvaluationIsValid(StrategyEvaluationevaluation);
3123
staticboolStrategyExpressionIsValid(StrategyExpressionexpression,
3224
StrategyNumbermaxStrategy);
33-
staticScanKeyStrategyMapGetScanKeyEntry(StrategyMapmap,
34-
StrategyNumberstrategyNumber);
3525
staticboolStrategyOperatorIsValid(StrategyOperatoroperator,
3626
StrategyNumbermaxStrategy);
3727
staticboolStrategyTermIsValid(StrategyTermterm,
@@ -63,7 +53,7 @@ static bool StrategyTermIsValid(StrategyTerm term,
6353
*Assumes that the index strategy number is valid.
6454
*Bounds checking should be done outside this routine.
6555
*/
66-
staticScanKey
56+
ScanKey
6757
StrategyMapGetScanKeyEntry(StrategyMapmap,
6858
StrategyNumberstrategyNumber)
6959
{
@@ -453,161 +443,6 @@ RelationInvokeStrategy(Relation relation,
453443
}
454444
#endif
455445

456-
/* ----------------
457-
*FillScanKeyEntry
458-
*
459-
* Initialize a ScanKey entry for the given operator OID.
460-
* ----------------
461-
*/
462-
staticvoid
463-
FillScanKeyEntry(OidoperatorObjectId,ScanKeyentry)
464-
{
465-
HeapTupletuple;
466-
467-
tuple=SearchSysCache(OPEROID,
468-
ObjectIdGetDatum(operatorObjectId),
469-
0,0,0);
470-
471-
if (!HeapTupleIsValid(tuple))
472-
elog(ERROR,"FillScanKeyEntry: unknown operator %u",
473-
operatorObjectId);
474-
475-
MemSet(entry,0,sizeof(*entry));
476-
entry->sk_flags=0;
477-
entry->sk_procedure= ((Form_pg_operator)GETSTRUCT(tuple))->oprcode;
478-
479-
ReleaseSysCache(tuple);
480-
481-
if (!RegProcedureIsValid(entry->sk_procedure))
482-
elog(ERROR,"FillScanKeyEntry: no procedure for operator %u",
483-
operatorObjectId);
484-
485-
/*
486-
* Mark entry->sk_func invalid, until and unless someone sets it up.
487-
*/
488-
entry->sk_func.fn_oid=InvalidOid;
489-
}
490-
491-
492-
/*
493-
* IndexSupportInitialize
494-
*Initializes an index strategy and associated support procedures.
495-
*
496-
* Data is returned into *indexStrategy, *indexSupport, and *isUnique,
497-
* all of which are objects allocated by the caller.
498-
*
499-
* The primary input keys are indexObjectId and accessMethodObjectId.
500-
* The caller also passes maxStrategyNumber, maxSupportNumber, and
501-
* maxAttributeNumber, since these indicate the size of the indexStrategy
502-
* and indexSupport arrays it has allocated --- but in practice these
503-
* numbers must always match those obtainable from the system catalog
504-
* entries for the index and access method.
505-
*/
506-
void
507-
IndexSupportInitialize(IndexStrategyindexStrategy,
508-
RegProcedure*indexSupport,
509-
bool*isUnique,
510-
OidindexObjectId,
511-
OidaccessMethodObjectId,
512-
StrategyNumbermaxStrategyNumber,
513-
StrategyNumbermaxSupportNumber,
514-
AttrNumbermaxAttributeNumber)
515-
{
516-
HeapTupletuple;
517-
Form_pg_indexiform;
518-
intattIndex;
519-
OidoperatorClassObjectId[INDEX_MAX_KEYS];
520-
521-
maxStrategyNumber=AMStrategies(maxStrategyNumber);
522-
523-
tuple=SearchSysCache(INDEXRELID,
524-
ObjectIdGetDatum(indexObjectId),
525-
0,0,0);
526-
if (!HeapTupleIsValid(tuple))
527-
elog(ERROR,"IndexSupportInitialize: no pg_index entry for index %u",
528-
indexObjectId);
529-
iform= (Form_pg_index)GETSTRUCT(tuple);
530-
531-
*isUnique=iform->indisunique;
532-
533-
/*
534-
* XXX note that the following assumes the INDEX tuple is well formed
535-
* and that the *key and *class are 0 terminated.
536-
*/
537-
for (attIndex=0;attIndex<maxAttributeNumber;attIndex++)
538-
{
539-
if (iform->indkey[attIndex]==InvalidAttrNumber||
540-
!OidIsValid(iform->indclass[attIndex]))
541-
elog(ERROR,"IndexSupportInitialize: bogus pg_index tuple");
542-
operatorClassObjectId[attIndex]=iform->indclass[attIndex];
543-
}
544-
545-
ReleaseSysCache(tuple);
546-
547-
/* if support routines exist for this access method, load them */
548-
if (maxSupportNumber>0)
549-
{
550-
for (attIndex=0;attIndex<maxAttributeNumber;attIndex++)
551-
{
552-
Oidopclass=operatorClassObjectId[attIndex];
553-
RegProcedure*loc;
554-
StrategyNumbersupport;
555-
556-
loc=&indexSupport[attIndex*maxSupportNumber];
557-
558-
for (support=0;support<maxSupportNumber;++support)
559-
{
560-
tuple=SearchSysCache(AMPROCNUM,
561-
ObjectIdGetDatum(opclass),
562-
Int16GetDatum(support+1),
563-
0,0);
564-
if (HeapTupleIsValid(tuple))
565-
{
566-
Form_pg_amprocamprocform;
567-
568-
amprocform= (Form_pg_amproc)GETSTRUCT(tuple);
569-
loc[support]=amprocform->amproc;
570-
ReleaseSysCache(tuple);
571-
}
572-
else
573-
loc[support]=InvalidOid;
574-
}
575-
}
576-
}
577-
578-
/* Now load the strategy information for the index operators */
579-
for (attIndex=0;attIndex<maxAttributeNumber;attIndex++)
580-
{
581-
Oidopclass=operatorClassObjectId[attIndex];
582-
StrategyMapmap;
583-
StrategyNumberstrategy;
584-
585-
map=IndexStrategyGetStrategyMap(indexStrategy,
586-
maxStrategyNumber,
587-
attIndex+1);
588-
589-
for (strategy=1;strategy <=maxStrategyNumber;strategy++)
590-
{
591-
ScanKeymapentry=StrategyMapGetScanKeyEntry(map,strategy);
592-
593-
tuple=SearchSysCache(AMOPSTRATEGY,
594-
ObjectIdGetDatum(opclass),
595-
Int16GetDatum(strategy),
596-
0,0);
597-
if (HeapTupleIsValid(tuple))
598-
{
599-
Form_pg_amopamopform;
600-
601-
amopform= (Form_pg_amop)GETSTRUCT(tuple);
602-
FillScanKeyEntry(amopform->amopopr,mapentry);
603-
ReleaseSysCache(tuple);
604-
}
605-
else
606-
ScanKeyEntrySetIllegal(mapentry);
607-
}
608-
}
609-
}
610-
611446
/* ----------------
612447
*IndexStrategyDisplay
613448
* ----------------

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp