mirror of
https://github.com/postgres/postgres.git
synced 2025-12-10 14:22:35 +03:00
Avoid pointer chasing in _bt_readpage inner loop.
Make _bt_readpage pass down the current scan direction to various utility functions within its pstate variable. Also have _bt_readpage work off of a local copy of scan->ignore_killed_tuples within its per-tuple loop (rather than using scan->ignore_killed_tuples directly). Testing has shown that this significantly benefits large range scans, which are naturally able to take full advantage of the pstate.startikey optimization added by commit8a510275. Running a pgbench script with a "SELECT abalance FROM pgbench_accounts WHERE aid BETWEEN ..." query shows an increase in transaction throughput of over 5%. There also appears to be a small performance benefit when running pgbench's built-in select-only script. Follow-up to commit65d6acbc. Author: Peter Geoghegan <pg@bowt.ie> Reviewed-By: Victor Yegorov <vyegorov@gmail.com> Discussion: https://postgr.es/m/CAH2-WzmwMwcwKFgaf+mYPwiz3iL4AqpXnwtW_O0vqpWPXRom9Q@mail.gmail.com
This commit is contained in:
@@ -31,6 +31,7 @@
|
|||||||
typedef struct BTReadPageState
|
typedef struct BTReadPageState
|
||||||
{
|
{
|
||||||
/* Input parameters, set by _bt_readpage for _bt_checkkeys */
|
/* Input parameters, set by _bt_readpage for _bt_checkkeys */
|
||||||
|
ScanDirection dir; /* current scan direction */
|
||||||
OffsetNumber minoff; /* Lowest non-pivot tuple's offset */
|
OffsetNumber minoff; /* Lowest non-pivot tuple's offset */
|
||||||
OffsetNumber maxoff; /* Highest non-pivot tuple's offset */
|
OffsetNumber maxoff; /* Highest non-pivot tuple's offset */
|
||||||
IndexTuple finaltup; /* Needed by scans with array keys */
|
IndexTuple finaltup; /* Needed by scans with array keys */
|
||||||
@@ -140,7 +141,8 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
|
|||||||
OffsetNumber minoff;
|
OffsetNumber minoff;
|
||||||
OffsetNumber maxoff;
|
OffsetNumber maxoff;
|
||||||
BTReadPageState pstate;
|
BTReadPageState pstate;
|
||||||
bool arrayKeys;
|
bool arrayKeys,
|
||||||
|
ignore_killed_tuples = scan->ignore_killed_tuples;
|
||||||
int itemIndex,
|
int itemIndex,
|
||||||
indnatts;
|
indnatts;
|
||||||
|
|
||||||
@@ -151,7 +153,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
|
|||||||
so->currPos.prevPage = opaque->btpo_prev;
|
so->currPos.prevPage = opaque->btpo_prev;
|
||||||
so->currPos.nextPage = opaque->btpo_next;
|
so->currPos.nextPage = opaque->btpo_next;
|
||||||
/* delay setting so->currPos.lsn until _bt_drop_lock_and_maybe_pin */
|
/* delay setting so->currPos.lsn until _bt_drop_lock_and_maybe_pin */
|
||||||
so->currPos.dir = dir;
|
pstate.dir = so->currPos.dir = dir;
|
||||||
so->currPos.nextTupleOffset = 0;
|
so->currPos.nextTupleOffset = 0;
|
||||||
|
|
||||||
/* either moreRight or moreLeft should be set now (may be unset later) */
|
/* either moreRight or moreLeft should be set now (may be unset later) */
|
||||||
@@ -244,7 +246,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
|
|||||||
* If the scan specifies not to return killed tuples, then we
|
* If the scan specifies not to return killed tuples, then we
|
||||||
* treat a killed tuple as not passing the qual
|
* treat a killed tuple as not passing the qual
|
||||||
*/
|
*/
|
||||||
if (scan->ignore_killed_tuples && ItemIdIsDead(iid))
|
if (ignore_killed_tuples && ItemIdIsDead(iid))
|
||||||
{
|
{
|
||||||
offnum = OffsetNumberNext(offnum);
|
offnum = OffsetNumberNext(offnum);
|
||||||
continue;
|
continue;
|
||||||
@@ -402,7 +404,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum,
|
|||||||
* uselessly advancing to the page to the left. This is similar
|
* uselessly advancing to the page to the left. This is similar
|
||||||
* to the high key optimization used by forward scans.
|
* to the high key optimization used by forward scans.
|
||||||
*/
|
*/
|
||||||
if (scan->ignore_killed_tuples && ItemIdIsDead(iid))
|
if (ignore_killed_tuples && ItemIdIsDead(iid))
|
||||||
{
|
{
|
||||||
if (offnum > minoff)
|
if (offnum > minoff)
|
||||||
{
|
{
|
||||||
@@ -1157,8 +1159,8 @@ _bt_checkkeys(IndexScanDesc scan, BTReadPageState *pstate, bool arrayKeys,
|
|||||||
IndexTuple tuple, int tupnatts)
|
IndexTuple tuple, int tupnatts)
|
||||||
{
|
{
|
||||||
TupleDesc tupdesc = RelationGetDescr(scan->indexRelation);
|
TupleDesc tupdesc = RelationGetDescr(scan->indexRelation);
|
||||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
BTScanOpaque so PG_USED_FOR_ASSERTS_ONLY = (BTScanOpaque) scan->opaque;
|
||||||
ScanDirection dir = so->currPos.dir;
|
ScanDirection dir = pstate->dir;
|
||||||
int ikey = pstate->startikey;
|
int ikey = pstate->startikey;
|
||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
@@ -2059,8 +2061,7 @@ static void
|
|||||||
_bt_checkkeys_look_ahead(IndexScanDesc scan, BTReadPageState *pstate,
|
_bt_checkkeys_look_ahead(IndexScanDesc scan, BTReadPageState *pstate,
|
||||||
int tupnatts, TupleDesc tupdesc)
|
int tupnatts, TupleDesc tupdesc)
|
||||||
{
|
{
|
||||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
ScanDirection dir = pstate->dir;
|
||||||
ScanDirection dir = so->currPos.dir;
|
|
||||||
OffsetNumber aheadoffnum;
|
OffsetNumber aheadoffnum;
|
||||||
IndexTuple ahead;
|
IndexTuple ahead;
|
||||||
|
|
||||||
@@ -2193,7 +2194,7 @@ _bt_advance_array_keys(IndexScanDesc scan, BTReadPageState *pstate,
|
|||||||
{
|
{
|
||||||
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
BTScanOpaque so = (BTScanOpaque) scan->opaque;
|
||||||
Relation rel = scan->indexRelation;
|
Relation rel = scan->indexRelation;
|
||||||
ScanDirection dir = so->currPos.dir;
|
ScanDirection dir = pstate ? pstate->dir : ForwardScanDirection;
|
||||||
int arrayidx = 0;
|
int arrayidx = 0;
|
||||||
bool beyond_end_advance = false,
|
bool beyond_end_advance = false,
|
||||||
skip_array_advanced = false,
|
skip_array_advanced = false,
|
||||||
|
|||||||
Reference in New Issue
Block a user