mirror of
https://github.com/postgres/postgres.git
synced 2025-08-31 17:02:12 +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:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.48 2002/05/20 23:51:41 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.49 2002/05/24 18:57:55 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -22,6 +22,9 @@
|
||||
#include "executor/execdebug.h"
|
||||
|
||||
|
||||
static int _bt_getstrategynumber(RegProcedure sk_procedure, StrategyMap map);
|
||||
|
||||
|
||||
/*
|
||||
* _bt_mkscankey
|
||||
* Build a scan key that contains comparison data from itup
|
||||
@@ -174,6 +177,11 @@ _bt_formitem(IndexTuple itup)
|
||||
* attribute, which can be seen to be correct by considering the above
|
||||
* example.
|
||||
*
|
||||
* Furthermore, we detect the case where the index is unique and we have
|
||||
* equality quals for all columns. In this case there can be at most one
|
||||
* (visible) matching tuple. index_getnext uses this to avoid uselessly
|
||||
* continuing the scan after finding one match.
|
||||
*
|
||||
* The initial ordering of the keys is expected to be by attribute already
|
||||
* (see group_clauses_by_indexkey() in indxpath.c). The task here is to
|
||||
* standardize the appearance of multiple keys for the same attribute.
|
||||
@@ -191,8 +199,10 @@ _bt_formitem(IndexTuple itup)
|
||||
*----------
|
||||
*/
|
||||
void
|
||||
_bt_orderkeys(Relation relation, BTScanOpaque so)
|
||||
_bt_orderkeys(IndexScanDesc scan)
|
||||
{
|
||||
Relation relation = scan->indexRelation;
|
||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
||||
ScanKeyData xform[BTMaxStrategyNumber];
|
||||
bool init[BTMaxStrategyNumber];
|
||||
int numberOfKeys = so->numberOfKeys;
|
||||
@@ -208,6 +218,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
||||
|
||||
so->qual_ok = true;
|
||||
so->numberOfRequiredKeys = 0;
|
||||
scan->keys_are_unique = false;
|
||||
|
||||
if (numberOfKeys < 1)
|
||||
return; /* done if qual-less scan */
|
||||
@@ -228,6 +239,17 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
||||
*/
|
||||
if (cur->sk_flags & SK_ISNULL)
|
||||
so->qual_ok = false;
|
||||
else if (relation->rd_index->indisunique &&
|
||||
relation->rd_rel->relnatts == 1)
|
||||
{
|
||||
/* it's a unique index, do we have an equality qual? */
|
||||
map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
|
||||
BTMaxStrategyNumber,
|
||||
1);
|
||||
j = _bt_getstrategynumber(cur->sk_procedure, map);
|
||||
if (j == (BTEqualStrategyNumber - 1))
|
||||
scan->keys_are_unique = true;
|
||||
}
|
||||
so->numberOfRequiredKeys = 1;
|
||||
return;
|
||||
}
|
||||
@@ -390,17 +412,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
||||
MemSet(init, 0, sizeof(init));
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, figure out which strategy this key corresponds to
|
||||
*/
|
||||
for (j = BTMaxStrategyNumber; --j >= 0;)
|
||||
{
|
||||
if (cur->sk_procedure == map->entry[j].sk_procedure)
|
||||
break;
|
||||
}
|
||||
if (j < 0)
|
||||
elog(ERROR, "_bt_orderkeys: unable to identify operator %u",
|
||||
cur->sk_procedure);
|
||||
/* figure out which strategy this key's operator corresponds to */
|
||||
j = _bt_getstrategynumber(cur->sk_procedure, map);
|
||||
|
||||
/* have we seen one of these before? */
|
||||
if (init[j])
|
||||
@@ -424,6 +437,34 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
||||
}
|
||||
|
||||
so->numberOfKeys = new_numberOfKeys;
|
||||
|
||||
/*
|
||||
* If unique index and we have equality keys for all columns,
|
||||
* set keys_are_unique flag for higher levels.
|
||||
*/
|
||||
if (allEqualSoFar && relation->rd_index->indisunique &&
|
||||
relation->rd_rel->relnatts == new_numberOfKeys)
|
||||
scan->keys_are_unique = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine which btree strategy an operator procedure matches.
|
||||
*
|
||||
* Result is strategy number minus 1.
|
||||
*/
|
||||
static int
|
||||
_bt_getstrategynumber(RegProcedure sk_procedure, StrategyMap map)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = BTMaxStrategyNumber; --j >= 0;)
|
||||
{
|
||||
if (sk_procedure == map->entry[j].sk_procedure)
|
||||
return j;
|
||||
}
|
||||
elog(ERROR, "_bt_getstrategynumber: unable to identify operator %u",
|
||||
sk_procedure);
|
||||
return -1; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user