Optimize seek operations on fts5 b-trees.

FossilOrigin-Name: 8cf02090ce53ec150492d77d9e5e5f27665bd34f
This commit is contained in:
dan 2015-07-04 18:44:07 +00:00
parent 01c5c00c12
commit 30ae503167
3 changed files with 121 additions and 22 deletions

View File

@ -2012,6 +2012,118 @@ static void fts5SegIterLoadDlidx(Fts5Index *p, Fts5SegIter *pIter){
pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
}
#ifdef SQLITE_DEBUG
static void fts5AssertNodeSeekOk(
Fts5Data *pNode,
const u8 *pTerm, int nTerm, /* Term to search for */
int iExpectPg,
int bExpectDlidx
){
int bDlidx;
int iPg;
int rc = SQLITE_OK;
Fts5NodeIter node;
fts5NodeIterInit(pNode->p, pNode->n, &node);
assert( node.term.n==0 );
iPg = node.iChild;
bDlidx = node.bDlidx;
for(fts5NodeIterNext(&rc, &node);
node.aData && fts5BufferCompareBlob(&node.term, pTerm, nTerm)<=0;
fts5NodeIterNext(&rc, &node)
){
iPg = node.iChild;
bDlidx = node.bDlidx;
}
fts5NodeIterFree(&node);
assert( rc!=SQLITE_OK || iPg==iExpectPg );
assert( rc!=SQLITE_OK || bDlidx==bExpectDlidx );
}
#else
#define fts5AssertNodeSeekOk(v,w,x,y,z)
#endif
/*
** Argument pNode is an internal b-tree node. This function searches
** within the node for the largest term that is smaller than or equal
** to (pTerm/nTerm).
**
** It returns the associated page number. Or, if (pTerm/nTerm) is smaller
** than all terms within the node, the leftmost child page number.
**
** Before returning, (*pbDlidx) is set to true if the last term on the
** returned child page number has a doclist-index. Or left as is otherwise.
*/
static int fts5NodeSeek(
Fts5Data *pNode, /* Node to search */
const u8 *pTerm, int nTerm, /* Term to search for */
int *pbDlidx /* OUT: True if dlidx flag is set */
){
int iPg;
u8 *pPtr = pNode->p;
u8 *pEnd = &pPtr[pNode->n];
int nMatch = 0; /* Number of bytes of pTerm already matched */
assert( *pbDlidx==0 );
pPtr += fts5GetVarint32(pPtr, iPg);
while( pPtr<pEnd ){
int nEmpty = 0;
int nKeep;
int nNew;
/* If there is a "no terms" record at pPtr, read it now. Store the
** number of termless pages in nEmpty. If it indicates a doclist-index,
** set (*pbDlidx) to true.*/
if( *pPtr<2 ){
*pbDlidx = (*pPtr==0x01);
pPtr++;
pPtr += fts5GetVarint32(pPtr, nEmpty);
}
/* Read the next "term" pointer. Set nKeep to the number of bytes to
** keep from the previous term, and nNew to the number of bytes of
** new data that will be appended to it. */
nKeep = (int)*pPtr++;
nNew = (int)*pPtr++;
if( (nKeep | nNew) & 0x0080 ){
pPtr -= 2;
pPtr += fts5GetVarint32(pPtr, nKeep);
pPtr += fts5GetVarint32(pPtr, nNew);
}
nKeep -= 2;
/* Compare (pTerm/nTerm) to the current term on the node (the one described
** by nKeep/nNew). If the node term is larger, break out of the while()
** loop.
**
** Otherwise, if (pTerm/nTerm) is larger or the two terms are equal,
** leave variable nMatch set to the size of the largest prefix common to
** both terms in bytes. */
if( nKeep==nMatch ){
int nTst = MIN(nNew, nTerm-nMatch);
int i;
for(i=0; i<nTst; i++){
if( pTerm[nKeep+i]!=pPtr[i] ) break;
}
nMatch += i;
assert( nMatch<=nTerm );
if( i<nNew && (nMatch==nTerm || pPtr[i] > pTerm[nMatch]) ) break;
}else if( nKeep<nMatch ){
break;
}
iPg += 1 + nEmpty;
*pbDlidx = 0;
pPtr += nNew;
}
fts5AssertNodeSeekOk(pNode, pTerm, nTerm, iPg, *pbDlidx);
return iPg;
}
/*
** Initialize the object pIter to point to term pTerm/nTerm within segment
** pSeg. If there is no such term in the index, the iterator is set to EOF.
@ -2040,24 +2152,11 @@ static void fts5SegIterSeekInit(
/* This block sets stack variable iPg to the leaf page number that may
** contain term (pTerm/nTerm), if it is present in the segment. */
for(h=pSeg->nHeight-1; h>0; h--){
Fts5NodeIter node; /* For iterating through internal nodes */
i64 iRowid = FTS5_SEGMENT_ROWID(pSeg->iSegid, h, iPg);
Fts5Data *pNode = fts5DataRead(p, iRowid);
if( pNode==0 ) break;
fts5NodeIterInit(pNode->p, pNode->n, &node);
assert( node.term.n==0 );
iPg = node.iChild;
bDlidx = node.bDlidx;
for(fts5NodeIterNext(&p->rc, &node);
node.aData && fts5BufferCompareBlob(&node.term, pTerm, nTerm)<=0;
fts5NodeIterNext(&p->rc, &node)
){
iPg = node.iChild;
bDlidx = node.bDlidx;
}
fts5NodeIterFree(&node);
iPg = fts5NodeSeek(pNode, pTerm, nTerm, &bDlidx);
fts5DataRelease(pNode);
}

View File

@ -1,5 +1,5 @@
C Preserve\sthe\snumber\sof\srequested\sPAGECACHE\spages\seven\sif\sthe\smemory\spointer\nor\ssize\sis\szero.\s\sEnhance\sthe\spcache1.c\sheader\scomment\sto\sexplain\sthe\smemory\nlayout\sof\sa\spage\scache\sline.
D 2015-07-04T18:15:04.326
C Optimize\sseek\soperations\son\sfts5\sb-trees.
D 2015-07-04T18:44:07.139
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 017bf0511d1b2dd1db5e16488fbf75a17b526cbc
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -112,7 +112,7 @@ F ext/fts5/fts5_buffer.c 80f9ba4431848cb857e3d2158f5280093dcd8015
F ext/fts5/fts5_config.c b2456e9625bca41c51d54c363e369c6356895c90
F ext/fts5/fts5_expr.c d2e148345639c5a5583e0daa39a639bf298ae6a7
F ext/fts5/fts5_hash.c 219f4edd72e5cf95b19c33f1058809a18fad5229
F ext/fts5/fts5_index.c 6564c103148e8b59d6b816f34d0b31f5f4025054
F ext/fts5/fts5_index.c 6224454702f852392cae8755c920f93b06b09283
F ext/fts5/fts5_main.c 37b0055cb4036c4b4bb4eb36e30ebd1c21c63939
F ext/fts5/fts5_storage.c 4cae85b5287b159d9d98174a4e70adf872b0930a
F ext/fts5/fts5_tcl.c 85eb4e0d0fefa9420b78151496ad4599a1783e20
@ -1364,7 +1364,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 4e473559c9bdcf4d0b823e995a3642cd50ebd337
R 3bd4765a55a11bf2fbafbabfd8169c43
U drh
Z 0199ebd97104f84a289dac04b3e8dc79
P dacb2a615ce1c0573baf4518000454038745cf2a
R a74787a76aedf64f2fa9d52272be4a28
U dan
Z 70c5b32ed488e093070d3138a449d5f1

View File

@ -1 +1 @@
dacb2a615ce1c0573baf4518000454038745cf2a
8cf02090ce53ec150492d77d9e5e5f27665bd34f