]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Optimize seek operations on fts5 b-trees.
authordan <dan@noemail.net>
Sat, 4 Jul 2015 18:44:07 +0000 (18:44 +0000)
committerdan <dan@noemail.net>
Sat, 4 Jul 2015 18:44:07 +0000 (18:44 +0000)
FossilOrigin-Name: 8cf02090ce53ec150492d77d9e5e5f27665bd34f

ext/fts5/fts5_index.c
manifest
manifest.uuid

index d29ee04a152743b3bb50d45d632c9963ff4e08f2..ae3ff35dbbe34ff78ae0ecca83943ee06da95125 100644 (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);
   }
 
index 380f99bcb1b912a0213b5d2c3e5e5d1d3618e0bc..23e00d3b333d9a55a354028348b774dd2bd5cac6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index 67c01f1a49cf5ff580f43880a11f0eb8fd2b8526..85d4c607807569e961f598ad98aa25023976550d 100644 (file)
@@ -1 +1 @@
-dacb2a615ce1c0573baf4518000454038745cf2a
\ No newline at end of file
+8cf02090ce53ec150492d77d9e5e5f27665bd34f
\ No newline at end of file