mirror of
https://github.com/postgres/postgres.git
synced 2025-10-24 01:29:19 +03:00
Mark index entries "killed" when they are no longer visible to any
transaction, so as to avoid returning them out of the index AM. Saves repeated heap_fetch operations on frequently-updated rows. Also detect queries on unique keys (equality to all columns of a unique index), and don't bother continuing scan once we have found first match. Killing is implemented in the btree and hash AMs, but not yet in rtree or gist, because there isn't an equally convenient place to do it in those AMs (the outer amgetnext routine can't do it without re-pinning the index page). Did some small cleanup on APIs of HeapTupleSatisfies, heap_fetch, and index_insert to make this a little easier.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: genam.h,v 1.34 2002/05/20 23:51:43 tgl Exp $
|
||||
* $Id: genam.h,v 1.35 2002/05/24 18:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -54,7 +54,8 @@ extern void index_close(Relation relation);
|
||||
extern InsertIndexResult index_insert(Relation indexRelation,
|
||||
Datum *datums, char *nulls,
|
||||
ItemPointer heap_t_ctid,
|
||||
Relation heapRelation);
|
||||
Relation heapRelation,
|
||||
bool check_uniqueness);
|
||||
|
||||
extern IndexScanDesc index_beginscan(Relation heapRelation,
|
||||
Relation indexRelation,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: heapam.h,v 1.75 2002/05/21 22:05:55 tgl Exp $
|
||||
* $Id: heapam.h,v 1.76 2002/05/24 18:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -152,8 +152,8 @@ extern void heap_rescan(HeapScanDesc scan, ScanKey key);
|
||||
extern void heap_endscan(HeapScanDesc scan);
|
||||
extern HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction);
|
||||
|
||||
extern void heap_fetch(Relation relation, Snapshot snapshot,
|
||||
HeapTuple tuple, Buffer *userbuf,
|
||||
extern bool heap_fetch(Relation relation, Snapshot snapshot,
|
||||
HeapTuple tuple, Buffer *userbuf, bool keep_buf,
|
||||
PgStat_Info *pgstat_info);
|
||||
|
||||
extern ItemPointer heap_get_latest_tid(Relation relation, Snapshot snapshot,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: nbtree.h,v 1.60 2002/05/20 23:51:43 tgl Exp $
|
||||
* $Id: nbtree.h,v 1.61 2002/05/24 18:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -383,7 +383,7 @@ extern ScanKey _bt_mkscankey(Relation rel, IndexTuple itup);
|
||||
extern ScanKey _bt_mkscankey_nodata(Relation rel);
|
||||
extern void _bt_freeskey(ScanKey skey);
|
||||
extern void _bt_freestack(BTStack stack);
|
||||
extern void _bt_orderkeys(Relation relation, BTScanOpaque so);
|
||||
extern void _bt_orderkeys(IndexScanDesc scan);
|
||||
extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple,
|
||||
ScanDirection dir, bool *continuescan);
|
||||
extern BTItem _bt_formitem(IndexTuple itup);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: relscan.h,v 1.26 2002/05/20 23:51:43 tgl Exp $
|
||||
* $Id: relscan.h,v 1.27 2002/05/24 18:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -46,7 +46,15 @@ typedef struct IndexScanDescData
|
||||
int numberOfKeys; /* number of scan keys */
|
||||
ScanKey keyData; /* array of scan key descriptors */
|
||||
|
||||
/* signaling to index AM about killing index tuples */
|
||||
bool kill_prior_tuple; /* last-returned tuple is dead */
|
||||
bool ignore_killed_tuples; /* do not return killed entries */
|
||||
|
||||
/* set by index AM if scan keys satisfy index's uniqueness constraint */
|
||||
bool keys_are_unique;
|
||||
|
||||
/* scan current state */
|
||||
bool got_tuple; /* true after successful index_getnext */
|
||||
void *opaque; /* access-method-specific info */
|
||||
ItemPointerData currentItemData; /* current index pointer */
|
||||
ItemPointerData currentMarkData; /* marked position, if any */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: valid.h,v 1.26 2001/11/05 17:46:31 momjian Exp $
|
||||
* $Id: valid.h,v 1.27 2002/05/24 18:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -77,14 +77,9 @@ do \
|
||||
/* ----------------
|
||||
* HeapTupleSatisfies
|
||||
*
|
||||
* Returns a valid HeapTuple if it satisfies the timequal and keytest.
|
||||
* Returns NULL otherwise. Used to be heap_satisifies (sic) which
|
||||
* returned a boolean. It now returns a tuple so that we can avoid doing two
|
||||
* PageGetItem's per tuple.
|
||||
*
|
||||
* Complete check of validity including LP_CTUP and keytest.
|
||||
* This should perhaps be combined with valid somehow in the
|
||||
* future. (Also, additional rule tests/time range tests.)
|
||||
* res is set TRUE if the HeapTuple satisfies the timequal and keytest,
|
||||
* otherwise it is set FALSE. Note that the hint bits in the HeapTuple's
|
||||
* t_infomask may be updated as a side effect.
|
||||
*
|
||||
* on 8/21/92 mao says: i rearranged the tests here to do keytest before
|
||||
* SatisfiesTimeQual. profiling indicated that even for vacuumed relations,
|
||||
@@ -100,35 +95,28 @@ do \
|
||||
disk_page, \
|
||||
seeself, \
|
||||
nKeys, \
|
||||
key) \
|
||||
key, \
|
||||
res) \
|
||||
do \
|
||||
{ \
|
||||
/* We use underscores to protect the variable passed in as parameters */ \
|
||||
bool _res; \
|
||||
\
|
||||
if ((key) != NULL) \
|
||||
HeapKeyTest(tuple, RelationGetDescr(relation), \
|
||||
(nKeys), (key), _res); \
|
||||
(nKeys), (key), (res)); \
|
||||
else \
|
||||
_res = TRUE; \
|
||||
(res) = true; \
|
||||
\
|
||||
if (_res) \
|
||||
if (res) \
|
||||
{ \
|
||||
if ((relation)->rd_rel->relkind != RELKIND_UNCATALOGED) \
|
||||
{ \
|
||||
uint16 _infomask = (tuple)->t_data->t_infomask; \
|
||||
\
|
||||
_res = HeapTupleSatisfiesVisibility((tuple), (seeself)); \
|
||||
(res) = HeapTupleSatisfiesVisibility((tuple), (seeself)); \
|
||||
if ((tuple)->t_data->t_infomask != _infomask) \
|
||||
SetBufferCommitInfoNeedsSave(buffer); \
|
||||
if (!_res) \
|
||||
(tuple)->t_data = NULL; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(tuple)->t_data = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* VALID_H */
|
||||
|
||||
Reference in New Issue
Block a user