aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/nbtree/nbtutils.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-10-09 00:21:08 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-10-09 00:21:08 -0400
commitcbfa92c23c3924d53889320cdbe26f23ee23e40c (patch)
treef93756a2e9f1d7e6cbf468b16528f275c04f04e5 /src/backend/access/nbtree/nbtutils.c
parent45401c1c25fe1ef14bf68089de86bcb5cce9f453 (diff)
downloadpostgresql-cbfa92c23c3924d53889320cdbe26f23ee23e40c.tar.gz
postgresql-cbfa92c23c3924d53889320cdbe26f23ee23e40c.zip
Improve index-only scans to avoid repeated access to the index page.
We copy all the matched tuples off the page during _bt_readpage, instead of expensively re-locking the page during each subsequent tuple fetch. This costs a bit more local storage, but not more than 2*BLCKSZ worth, and the reduction in LWLock traffic is certainly worth that. What's more, this lets us get rid of the API wart in the original patch that said an index AM could randomly decline to supply an index tuple despite having asserted pg_am.amcanreturn. That will be important for future improvements in the index-only-scan feature, since the executor will now be able to rely on having the index data available.
Diffstat (limited to 'src/backend/access/nbtree/nbtutils.c')
-rw-r--r--src/backend/access/nbtree/nbtutils.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 3ca75b79ccb..b6fb3867bf0 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -835,8 +835,8 @@ _bt_mark_scankey_required(ScanKey skey)
/*
* Test whether an indextuple satisfies all the scankey conditions.
*
- * If so, copy its TID into scan->xs_ctup.t_self, and return TRUE.
- * If not, return FALSE (xs_ctup is not changed).
+ * If so, return the address of the index tuple on the index page.
+ * If not, return NULL.
*
* If the tuple fails to pass the qual, we also determine whether there's
* any need to continue the scan beyond this tuple, and set *continuescan
@@ -848,14 +848,16 @@ _bt_mark_scankey_required(ScanKey skey)
* offnum: offset number of index tuple (must be a valid item!)
* dir: direction we are scanning in
* continuescan: output parameter (will be set correctly in all cases)
+ *
+ * Caller must hold pin and lock on the index page.
*/
-bool
+IndexTuple
_bt_checkkeys(IndexScanDesc scan,
Page page, OffsetNumber offnum,
ScanDirection dir, bool *continuescan)
{
ItemId iid = PageGetItemId(page, offnum);
- bool tuple_valid;
+ bool tuple_alive;
IndexTuple tuple;
TupleDesc tupdesc;
BTScanOpaque so;
@@ -879,24 +881,24 @@ _bt_checkkeys(IndexScanDesc scan,
if (ScanDirectionIsForward(dir))
{
if (offnum < PageGetMaxOffsetNumber(page))
- return false;
+ return NULL;
}
else
{
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
if (offnum > P_FIRSTDATAKEY(opaque))
- return false;
+ return NULL;
}
/*
- * OK, we want to check the keys, but we'll return FALSE even if the
- * tuple passes the key tests.
+ * OK, we want to check the keys so we can set continuescan correctly,
+ * but we'll return NULL even if the tuple passes the key tests.
*/
- tuple_valid = false;
+ tuple_alive = false;
}
else
- tuple_valid = true;
+ tuple_alive = true;
tuple = (IndexTuple) PageGetItem(page, iid);
@@ -915,7 +917,7 @@ _bt_checkkeys(IndexScanDesc scan,
{
if (_bt_check_rowcompare(key, tuple, tupdesc, dir, continuescan))
continue;
- return false;
+ return NULL;
}
datum = index_getattr(tuple,
@@ -953,7 +955,7 @@ _bt_checkkeys(IndexScanDesc scan,
/*
* In any case, this indextuple doesn't match the qual.
*/
- return false;
+ return NULL;
}
if (isNull)
@@ -988,7 +990,7 @@ _bt_checkkeys(IndexScanDesc scan,
/*
* In any case, this indextuple doesn't match the qual.
*/
- return false;
+ return NULL;
}
test = FunctionCall2Coll(&key->sk_func, key->sk_collation,
@@ -1016,15 +1018,16 @@ _bt_checkkeys(IndexScanDesc scan,
/*
* In any case, this indextuple doesn't match the qual.
*/
- return false;
+ return NULL;
}
}
- /* If we get here, the tuple passes all index quals. */
- if (tuple_valid)
- scan->xs_ctup.t_self = tuple->t_tid;
+ /* Check for failure due to it being a killed tuple. */
+ if (!tuple_alive)
+ return NULL;
- return tuple_valid;
+ /* If we get here, the tuple passes all index quals. */
+ return tuple;
}
/*