Currently,only the first column of multi-column indices
is used to find start scan position of Indexscan-s. To speed up finding scan start position,I have changed _bt_first() to use as many keys as possible. I'll attach the patch here. Regards. Hiroshi Inoue
This commit is contained in:
parent
62045e67eb
commit
7b2a8e4e56
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.53 1999/07/17 20:16:43 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.54 1999/09/27 18:20:21 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -727,11 +727,15 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
RegProcedure proc;
|
RegProcedure proc;
|
||||||
int result;
|
int result;
|
||||||
BTScanOpaque so;
|
BTScanOpaque so;
|
||||||
ScanKeyData skdata;
|
|
||||||
Size keysok;
|
Size keysok;
|
||||||
int i;
|
|
||||||
int nKeyIndex = -1;
|
|
||||||
|
|
||||||
|
bool strategyCheck;
|
||||||
|
ScanKey scankeys = 0;
|
||||||
|
int keysCount = 0;
|
||||||
|
int *nKeyIs = 0;
|
||||||
|
int i, j;
|
||||||
|
StrategyNumber strat_total;
|
||||||
|
|
||||||
rel = scan->relation;
|
rel = scan->relation;
|
||||||
so = (BTScanOpaque) scan->opaque;
|
so = (BTScanOpaque) scan->opaque;
|
||||||
|
|
||||||
@ -742,38 +746,57 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
so->numberOfFirstKeys = 0; /* may be changed by _bt_orderkeys */
|
so->numberOfFirstKeys = 0; /* may be changed by _bt_orderkeys */
|
||||||
so->qual_ok = 1; /* may be changed by _bt_orderkeys */
|
so->qual_ok = 1; /* may be changed by _bt_orderkeys */
|
||||||
scan->scanFromEnd = false;
|
scan->scanFromEnd = false;
|
||||||
|
strategyCheck = false;
|
||||||
if (so->numberOfKeys > 0)
|
if (so->numberOfKeys > 0)
|
||||||
{
|
{
|
||||||
_bt_orderkeys(rel, so);
|
_bt_orderkeys(rel, so);
|
||||||
|
|
||||||
if (ScanDirectionIsBackward(dir))
|
if (so->qual_ok)
|
||||||
|
strategyCheck = true;
|
||||||
|
}
|
||||||
|
strat_total = BTEqualStrategyNumber;
|
||||||
|
if (strategyCheck)
|
||||||
|
{
|
||||||
|
AttrNumber attno;
|
||||||
|
|
||||||
|
nKeyIs = (int *)palloc(so->numberOfKeys*sizeof(int));
|
||||||
|
for (i=0; i < so->numberOfKeys; i++)
|
||||||
{
|
{
|
||||||
for (i = 0; i < so->numberOfKeys; i++)
|
attno = so->keyData[i].sk_attno;
|
||||||
|
if (attno == keysCount)
|
||||||
|
continue;
|
||||||
|
if (attno > keysCount + 1)
|
||||||
|
break;
|
||||||
|
strat = _bt_getstrat(rel, attno,
|
||||||
|
so->keyData[i].sk_procedure);
|
||||||
|
if (strat == strat_total ||
|
||||||
|
strat == BTEqualStrategyNumber)
|
||||||
{
|
{
|
||||||
if (so->keyData[i].sk_attno != 1)
|
nKeyIs[keysCount++] = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ScanDirectionIsBackward(dir) &&
|
||||||
|
(strat == BTLessStrategyNumber ||
|
||||||
|
strat == BTLessEqualStrategyNumber) )
|
||||||
|
{
|
||||||
|
nKeyIs[keysCount++] = i;
|
||||||
|
strat_total = strat;
|
||||||
|
if (strat == BTLessStrategyNumber)
|
||||||
break;
|
break;
|
||||||
strat = _bt_getstrat(rel, so->keyData[i].sk_attno,
|
continue;
|
||||||
so->keyData[i].sk_procedure);
|
}
|
||||||
if (strat == BTLessStrategyNumber ||
|
if (ScanDirectionIsForward(dir) &&
|
||||||
strat == BTLessEqualStrategyNumber ||
|
(strat == BTGreaterStrategyNumber ||
|
||||||
strat == BTEqualStrategyNumber)
|
strat == BTGreaterEqualStrategyNumber) )
|
||||||
{
|
{
|
||||||
nKeyIndex = i;
|
nKeyIs[keysCount++] = i;
|
||||||
|
strat_total = strat;
|
||||||
|
if (strat == BTGreaterStrategyNumber)
|
||||||
break;
|
break;
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
if (!keysCount)
|
||||||
{
|
|
||||||
strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
|
|
||||||
|
|
||||||
if (strat == BTLessStrategyNumber ||
|
|
||||||
strat == BTLessEqualStrategyNumber)
|
|
||||||
;
|
|
||||||
else
|
|
||||||
nKeyIndex = 0;
|
|
||||||
}
|
|
||||||
if (nKeyIndex < 0)
|
|
||||||
scan->scanFromEnd = true;
|
scan->scanFromEnd = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -784,7 +807,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
/* if we just need to walk down one edge of the tree, do that */
|
/* if we just need to walk down one edge of the tree, do that */
|
||||||
if (scan->scanFromEnd)
|
if (scan->scanFromEnd)
|
||||||
|
{
|
||||||
|
if (nKeyIs)
|
||||||
|
pfree(nKeyIs);
|
||||||
return _bt_endpoint(scan, dir);
|
return _bt_endpoint(scan, dir);
|
||||||
|
}
|
||||||
|
|
||||||
itupdesc = RelationGetDescr(rel);
|
itupdesc = RelationGetDescr(rel);
|
||||||
current = &(scan->currentItemData);
|
current = &(scan->currentItemData);
|
||||||
@ -796,16 +823,24 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
* at the right place in the scan.
|
* at the right place in the scan.
|
||||||
*/
|
*/
|
||||||
/* _bt_orderkeys disallows it, but it's place to add some code latter */
|
/* _bt_orderkeys disallows it, but it's place to add some code latter */
|
||||||
if (so->keyData[0].sk_flags & SK_ISNULL)
|
scankeys = (ScanKey)palloc(keysCount*sizeof(ScanKeyData));
|
||||||
|
for (i=0; i < keysCount; i++)
|
||||||
{
|
{
|
||||||
elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet");
|
j = nKeyIs[i];
|
||||||
return (RetrieveIndexResult) NULL;
|
if (so->keyData[j].sk_flags & SK_ISNULL)
|
||||||
|
{
|
||||||
|
pfree(nKeyIs);
|
||||||
|
pfree(scankeys);
|
||||||
|
elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet");
|
||||||
|
return ((RetrieveIndexResult) NULL);
|
||||||
|
}
|
||||||
|
proc = index_getprocid(rel, i+1, BTORDER_PROC);
|
||||||
|
ScanKeyEntryInitialize(scankeys+i, so->keyData[j].sk_flags,
|
||||||
|
i+1, proc, so->keyData[j].sk_argument);
|
||||||
}
|
}
|
||||||
proc = index_getprocid(rel, 1, BTORDER_PROC);
|
if (nKeyIs) pfree(nKeyIs);
|
||||||
ScanKeyEntryInitialize(&skdata, so->keyData[nKeyIndex].sk_flags,
|
|
||||||
1, proc, so->keyData[nKeyIndex].sk_argument);
|
|
||||||
|
|
||||||
stack = _bt_search(rel, 1, &skdata, &buf);
|
stack = _bt_search(rel, keysCount, scankeys, &buf);
|
||||||
_bt_freestack(stack);
|
_bt_freestack(stack);
|
||||||
|
|
||||||
blkno = BufferGetBlockNumber(buf);
|
blkno = BufferGetBlockNumber(buf);
|
||||||
@ -823,6 +858,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
ItemPointerSetInvalid(current);
|
ItemPointerSetInvalid(current);
|
||||||
so->btso_curbuf = InvalidBuffer;
|
so->btso_curbuf = InvalidBuffer;
|
||||||
_bt_relbuf(rel, buf, BT_READ);
|
_bt_relbuf(rel, buf, BT_READ);
|
||||||
|
pfree(scankeys);
|
||||||
return (RetrieveIndexResult) NULL;
|
return (RetrieveIndexResult) NULL;
|
||||||
}
|
}
|
||||||
maxoff = PageGetMaxOffsetNumber(page);
|
maxoff = PageGetMaxOffsetNumber(page);
|
||||||
@ -835,7 +871,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
while (maxoff == P_HIKEY && !P_RIGHTMOST(pop) &&
|
while (maxoff == P_HIKEY && !P_RIGHTMOST(pop) &&
|
||||||
_bt_skeycmp(rel, 1, &skdata, page,
|
_bt_skeycmp(rel, keysCount, scankeys, page,
|
||||||
PageGetItemId(page, P_HIKEY),
|
PageGetItemId(page, P_HIKEY),
|
||||||
BTGreaterEqualStrategyNumber))
|
BTGreaterEqualStrategyNumber))
|
||||||
{
|
{
|
||||||
@ -849,6 +885,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
ItemPointerSetInvalid(current);
|
ItemPointerSetInvalid(current);
|
||||||
so->btso_curbuf = InvalidBuffer;
|
so->btso_curbuf = InvalidBuffer;
|
||||||
_bt_relbuf(rel, buf, BT_READ);
|
_bt_relbuf(rel, buf, BT_READ);
|
||||||
|
pfree(scankeys);
|
||||||
return (RetrieveIndexResult) NULL;
|
return (RetrieveIndexResult) NULL;
|
||||||
}
|
}
|
||||||
maxoff = PageGetMaxOffsetNumber(page);
|
maxoff = PageGetMaxOffsetNumber(page);
|
||||||
@ -857,7 +894,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
|
|
||||||
/* find the nearest match to the manufactured scan key on the page */
|
/* find the nearest match to the manufactured scan key on the page */
|
||||||
offnum = _bt_binsrch(rel, buf, 1, &skdata, BT_DESCENT);
|
offnum = _bt_binsrch(rel, buf, keysCount, scankeys, BT_DESCENT);
|
||||||
|
|
||||||
if (offnum > maxoff)
|
if (offnum > maxoff)
|
||||||
{
|
{
|
||||||
@ -872,12 +909,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
* we're looking for minus the value we're looking at in the index.
|
* we're looking for minus the value we're looking at in the index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
|
result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
|
||||||
|
|
||||||
/* it's yet other place to add some code latter for is(not)null */
|
/* it's yet other place to add some code latter for is(not)null */
|
||||||
|
|
||||||
strat = _bt_getstrat(rel, 1, so->keyData[nKeyIndex].sk_procedure);
|
strat = strat_total;
|
||||||
|
|
||||||
switch (strat)
|
switch (strat)
|
||||||
{
|
{
|
||||||
case BTLessStrategyNumber:
|
case BTLessStrategyNumber:
|
||||||
@ -890,7 +926,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
|
result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
|
||||||
} while (result <= 0);
|
} while (result <= 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -906,12 +942,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
|
result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
|
||||||
} while (result >= 0);
|
} while (result >= 0);
|
||||||
|
|
||||||
if (result < 0)
|
|
||||||
_bt_twostep(scan, &buf, BackwardScanDirection);
|
|
||||||
}
|
}
|
||||||
|
if (result < 0)
|
||||||
|
_bt_twostep(scan, &buf, BackwardScanDirection);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BTEqualStrategyNumber:
|
case BTEqualStrategyNumber:
|
||||||
@ -920,6 +955,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
_bt_relbuf(scan->relation, buf, BT_READ);
|
_bt_relbuf(scan->relation, buf, BT_READ);
|
||||||
so->btso_curbuf = InvalidBuffer;
|
so->btso_curbuf = InvalidBuffer;
|
||||||
ItemPointerSetInvalid(&(scan->currentItemData));
|
ItemPointerSetInvalid(&(scan->currentItemData));
|
||||||
|
pfree(scankeys);
|
||||||
return (RetrieveIndexResult) NULL;
|
return (RetrieveIndexResult) NULL;
|
||||||
}
|
}
|
||||||
else if (ScanDirectionIsBackward(dir))
|
else if (ScanDirectionIsBackward(dir))
|
||||||
@ -931,7 +967,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
|
result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
|
||||||
} while (result == 0);
|
} while (result == 0);
|
||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
@ -950,6 +986,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
_bt_relbuf(scan->relation, buf, BT_READ);
|
_bt_relbuf(scan->relation, buf, BT_READ);
|
||||||
so->btso_curbuf = InvalidBuffer;
|
so->btso_curbuf = InvalidBuffer;
|
||||||
ItemPointerSetInvalid(&(scan->currentItemData));
|
ItemPointerSetInvalid(&(scan->currentItemData));
|
||||||
|
pfree(scankeys);
|
||||||
return (RetrieveIndexResult) NULL;
|
return (RetrieveIndexResult) NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -974,7 +1011,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
|
result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
|
||||||
} while (result < 0);
|
} while (result < 0);
|
||||||
|
|
||||||
if (result > 0)
|
if (result > 0)
|
||||||
@ -993,12 +1030,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
|||||||
|
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
|
result = _bt_compare(rel, itupdesc, page, keysCount, scankeys, offnum);
|
||||||
} while (result >= 0);
|
} while (result >= 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pfree(scankeys);
|
||||||
/* okay, current item pointer for the scan is right */
|
/* okay, current item pointer for the scan is right */
|
||||||
offnum = ItemPointerGetOffsetNumber(current);
|
offnum = ItemPointerGetOffsetNumber(current);
|
||||||
page = BufferGetPage(buf);
|
page = BufferGetPage(buf);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.32 1999/07/17 20:16:43 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.33 1999/09/27 18:20:21 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -101,6 +101,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
|||||||
uint16 numberOfKeys = so->numberOfKeys;
|
uint16 numberOfKeys = so->numberOfKeys;
|
||||||
uint16 new_numberOfKeys = 0;
|
uint16 new_numberOfKeys = 0;
|
||||||
AttrNumber attno = 1;
|
AttrNumber attno = 1;
|
||||||
|
bool equalStrategyEnd, underEqualStrategy;
|
||||||
|
|
||||||
if (numberOfKeys < 1)
|
if (numberOfKeys < 1)
|
||||||
return;
|
return;
|
||||||
@ -136,6 +137,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
|||||||
for (j = 0; j <= BTMaxStrategyNumber; j++)
|
for (j = 0; j <= BTMaxStrategyNumber; j++)
|
||||||
init[j] = 0;
|
init[j] = 0;
|
||||||
|
|
||||||
|
equalStrategyEnd = false;
|
||||||
|
underEqualStrategy = true;
|
||||||
/* check each key passed in */
|
/* check each key passed in */
|
||||||
for (i = 0;;)
|
for (i = 0;;)
|
||||||
{
|
{
|
||||||
@ -150,6 +153,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
|||||||
if (cur->sk_attno != attno + 1 && i < numberOfKeys)
|
if (cur->sk_attno != attno + 1 && i < numberOfKeys)
|
||||||
elog(ERROR, "_bt_orderkeys: key(s) for attribute %d missed", attno + 1);
|
elog(ERROR, "_bt_orderkeys: key(s) for attribute %d missed", attno + 1);
|
||||||
|
|
||||||
|
underEqualStrategy = (!equalStrategyEnd);
|
||||||
/*
|
/*
|
||||||
* If = has been specified, no other key will be used. In case
|
* If = has been specified, no other key will be used. In case
|
||||||
* of key < 2 && key == 1 and so on we have to set qual_ok to
|
* of key < 2 && key == 1 and so on we have to set qual_ok to
|
||||||
@ -175,6 +179,8 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
|||||||
init[BTGreaterEqualStrategyNumber - 1] = 0;
|
init[BTGreaterEqualStrategyNumber - 1] = 0;
|
||||||
init[BTGreaterStrategyNumber - 1] = 0;
|
init[BTGreaterStrategyNumber - 1] = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
equalStrategyEnd = true;
|
||||||
|
|
||||||
/* only one of <, <= */
|
/* only one of <, <= */
|
||||||
if (init[BTLessStrategyNumber - 1]
|
if (init[BTLessStrategyNumber - 1]
|
||||||
@ -223,7 +229,7 @@ _bt_orderkeys(Relation relation, BTScanOpaque so)
|
|||||||
if (init[j])
|
if (init[j])
|
||||||
key[new_numberOfKeys++] = xform[j];
|
key[new_numberOfKeys++] = xform[j];
|
||||||
|
|
||||||
if (attno == 1)
|
if (underEqualStrategy)
|
||||||
so->numberOfFirstKeys = new_numberOfKeys;
|
so->numberOfFirstKeys = new_numberOfKeys;
|
||||||
|
|
||||||
if (i == numberOfKeys)
|
if (i == numberOfKeys)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user