mirror of
https://github.com/postgres/postgres.git
synced 2025-07-12 21:01:52 +03:00
A bunch of changes aimed at reducing backend startup time...
Improve 'pg_internal.init' relcache entry preload mechanism so that it is safe to use for all system catalogs, and arrange to preload a realistic set of system-catalog entries instead of only the three nailed-in-cache indexes that were formerly loaded this way. Fix mechanism for deleting out-of-date pg_internal.init files: this must be synchronized with transaction commit, not just done at random times within transactions. Drive it off relcache invalidation mechanism so that no special-case tests are needed. Cache additional information in relcache entries for indexes (their pg_index tuples and index-operator OIDs) to eliminate repeated lookups. Also cache index opclass info at the per-opclass level to avoid repeated lookups during relcache load. Generalize 'systable scan' utilities originally developed by Hiroshi, move them into genam.c, use in a number of places where there was formerly ugly code for choosing either heap or index scan. In particular this allows simplification of the logic that prevents infinite recursion between syscache and relcache during startup: we can easily switch to heapscans in relcache.c when and where needed to avoid recursion, so IndexScanOK becomes simpler and does 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).
This commit is contained in:
@ -6,25 +6,12 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: execAmi.c,v 1.60 2001/10/25 05:49:27 momjian Exp $
|
||||
* $Id: execAmi.c,v 1.61 2002/02/19 20:11:13 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* INTERFACE ROUTINES
|
||||
*
|
||||
* ExecOpenScanR \ / amopen
|
||||
* ExecBeginScan \ / ambeginscan
|
||||
* ExecCloseR \ / amclose
|
||||
* ExecInsert \ executor interface / aminsert
|
||||
* ExecReScanR / to access methods \ amrescan
|
||||
* ExecMarkPos / \ ammarkpos
|
||||
* ExecRestrPos / \ amrestpos
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
|
||||
#include "access/genam.h"
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/heap.h"
|
||||
@ -50,202 +37,6 @@
|
||||
#include "executor/nodeSubqueryscan.h"
|
||||
#include "executor/nodeUnique.h"
|
||||
|
||||
static Pointer ExecBeginScan(Relation relation, int nkeys, ScanKey skeys,
|
||||
bool isindex, ScanDirection dir, Snapshot snapshot);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecOpenScanR
|
||||
*
|
||||
* old comments:
|
||||
* Parameters:
|
||||
* relation -- relation to be opened and scanned.
|
||||
* nkeys -- number of keys
|
||||
* skeys -- keys to restrict scanning
|
||||
* isindex -- if this is true, the relation is the relid of
|
||||
* an index relation, else it is a heap relation.
|
||||
* Returns the relation as(relDesc scanDesc)
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecOpenScanR(Oid relOid,
|
||||
int nkeys,
|
||||
ScanKey skeys,
|
||||
bool isindex,
|
||||
ScanDirection dir,
|
||||
Snapshot snapshot,
|
||||
Relation *returnRelation, /* return */
|
||||
Pointer *returnScanDesc) /* return */
|
||||
{
|
||||
Relation relation;
|
||||
Pointer scanDesc;
|
||||
|
||||
/*
|
||||
* note: scanDesc returned by ExecBeginScan can be either a
|
||||
* HeapScanDesc or an IndexScanDesc so for now we make it a Pointer.
|
||||
* There should be a better scan abstraction someday -cim 9/9/89
|
||||
*/
|
||||
|
||||
/*
|
||||
* Open the relation with the correct call depending on whether this
|
||||
* is a heap relation or an index relation.
|
||||
*
|
||||
* For a table, acquire AccessShareLock for the duration of the query
|
||||
* execution. For indexes, acquire no lock here; the index machinery
|
||||
* does its own locks and unlocks. (We rely on having some kind of
|
||||
* lock on the parent table to ensure the index won't go away!)
|
||||
*/
|
||||
if (isindex)
|
||||
relation = index_open(relOid);
|
||||
else
|
||||
relation = heap_open(relOid, AccessShareLock);
|
||||
|
||||
scanDesc = ExecBeginScan(relation,
|
||||
nkeys,
|
||||
skeys,
|
||||
isindex,
|
||||
dir,
|
||||
snapshot);
|
||||
|
||||
if (returnRelation != NULL)
|
||||
*returnRelation = relation;
|
||||
if (scanDesc != NULL)
|
||||
*returnScanDesc = scanDesc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecBeginScan
|
||||
*
|
||||
* beginscans a relation in current direction.
|
||||
*
|
||||
* XXX fix parameters to AMbeginscan (and btbeginscan)
|
||||
* currently we need to pass a flag stating whether
|
||||
* or not the scan should begin at an endpoint of
|
||||
* the relation.. Right now we always pass false
|
||||
* -cim 9/14/89
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
static Pointer
|
||||
ExecBeginScan(Relation relation,
|
||||
int nkeys,
|
||||
ScanKey skeys,
|
||||
bool isindex,
|
||||
ScanDirection dir,
|
||||
Snapshot snapshot)
|
||||
{
|
||||
Pointer scanDesc;
|
||||
|
||||
/*
|
||||
* open the appropriate type of scan.
|
||||
*
|
||||
* Note: ambeginscan()'s second arg is a boolean indicating that the scan
|
||||
* should be done in reverse.. That is, if you pass it true, then the
|
||||
* scan is backward.
|
||||
*/
|
||||
if (isindex)
|
||||
{
|
||||
scanDesc = (Pointer) index_beginscan(relation,
|
||||
false, /* see above comment */
|
||||
nkeys,
|
||||
skeys);
|
||||
}
|
||||
else
|
||||
{
|
||||
scanDesc = (Pointer) heap_beginscan(relation,
|
||||
ScanDirectionIsBackward(dir),
|
||||
snapshot,
|
||||
nkeys,
|
||||
skeys);
|
||||
}
|
||||
|
||||
if (scanDesc == NULL)
|
||||
elog(DEBUG, "ExecBeginScan: scanDesc = NULL, heap_beginscan failed.");
|
||||
|
||||
return scanDesc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecCloseR
|
||||
*
|
||||
* closes the relation and scan descriptor for a scan node.
|
||||
* Also closes index relations and scans for index scans.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
ExecCloseR(Plan *node)
|
||||
{
|
||||
CommonScanState *state;
|
||||
Relation relation;
|
||||
HeapScanDesc scanDesc;
|
||||
|
||||
/*
|
||||
* get state for node and shut down the heap scan, if any
|
||||
*/
|
||||
switch (nodeTag(node))
|
||||
{
|
||||
case T_SeqScan:
|
||||
state = ((SeqScan *) node)->scanstate;
|
||||
break;
|
||||
|
||||
case T_IndexScan:
|
||||
state = ((IndexScan *) node)->scan.scanstate;
|
||||
break;
|
||||
|
||||
case T_TidScan:
|
||||
state = ((TidScan *) node)->scan.scanstate;
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(DEBUG, "ExecCloseR: not a scan node!");
|
||||
return;
|
||||
}
|
||||
|
||||
relation = state->css_currentRelation;
|
||||
scanDesc = state->css_currentScanDesc;
|
||||
|
||||
if (scanDesc != NULL)
|
||||
heap_endscan(scanDesc);
|
||||
|
||||
/*
|
||||
* if this is an index scan then we have to take care of the index
|
||||
* relations as well.
|
||||
*/
|
||||
if (IsA(node, IndexScan))
|
||||
{
|
||||
IndexScan *iscan = (IndexScan *) node;
|
||||
IndexScanState *indexstate = iscan->indxstate;
|
||||
int numIndices;
|
||||
RelationPtr indexRelationDescs;
|
||||
IndexScanDescPtr indexScanDescs;
|
||||
int i;
|
||||
|
||||
numIndices = indexstate->iss_NumIndices;
|
||||
indexRelationDescs = indexstate->iss_RelationDescs;
|
||||
indexScanDescs = indexstate->iss_ScanDescs;
|
||||
|
||||
for (i = 0; i < numIndices; i++)
|
||||
{
|
||||
/*
|
||||
* shut down each of the index scans and close each of the
|
||||
* index relations
|
||||
*/
|
||||
if (indexScanDescs[i] != NULL)
|
||||
index_endscan(indexScanDescs[i]);
|
||||
|
||||
if (indexRelationDescs[i] != NULL)
|
||||
index_close(indexRelationDescs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, close the heap relation.
|
||||
*
|
||||
* Currently, we do not release the AccessShareLock acquired by
|
||||
* ExecOpenScanR. This lock should be held till end of transaction.
|
||||
* (There is a faction that considers this too much locking, however.)
|
||||
*/
|
||||
if (relation != NULL)
|
||||
heap_close(relation, NoLock);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecReScan
|
||||
@ -374,27 +165,6 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecReScanR
|
||||
*
|
||||
* XXX this does not do the right thing with indices yet.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
HeapScanDesc
|
||||
ExecReScanR(Relation relDesc, /* LLL relDesc unused */
|
||||
HeapScanDesc scanDesc,
|
||||
ScanDirection direction,
|
||||
int nkeys, /* LLL nkeys unused */
|
||||
ScanKey skeys)
|
||||
{
|
||||
if (scanDesc != NULL)
|
||||
heap_rescan(scanDesc, /* scan desc */
|
||||
ScanDirectionIsBackward(direction), /* backward flag */
|
||||
skeys); /* scan keys */
|
||||
|
||||
return scanDesc;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecMarkPos
|
||||
*
|
||||
|
Reference in New Issue
Block a user