]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The query planner uses non-indexable WHERE clause terms to reduce the
authordrh <drh@noemail.net>
Wed, 14 Apr 2010 19:01:44 +0000 (19:01 +0000)
committerdrh <drh@noemail.net>
Wed, 14 Apr 2010 19:01:44 +0000 (19:01 +0000)
estimated number of output rows, then uses the estimated number of output
rows as a tie-breaker when choosing table order.

FossilOrigin-Name: b87cb0c2bd9c52a938795a974e101879b81210e3

manifest
manifest.uuid
src/where.c

index 00922039512bd3c5f8df83fa905291c9b283c89f..552af60972b0b6d404cb212772976f07c8b3538f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,8 @@
-C Test\sthat\sthe\srollback-hook\sis\sinvoked\sif\sa\scommit-hook\simplementation\sreturns\snon-zero\s(causing\sa\srollback).\sRemove\sdocumentation\scomment\sthat\ssays\sotherwise\sfrom\ssqlite.h.in.
-D 2010-04-13T06:18:02
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+C The\squery\splanner\suses\snon-indexable\sWHERE\sclause\sterms\sto\sreduce\sthe\nestimated\snumber\sof\soutput\srows,\sthen\suses\sthe\sestimated\snumber\sof\soutput\nrows\sas\sa\stie-breaker\swhen\schoosing\stable\sorder.
+D 2010-04-14T19:01:45
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -222,7 +225,7 @@ F src/vdbemem.c 2a82f455f6ca6f78b59fb312f96054c04ae0ead1
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c 9472b11332699aff0f8926dbe6175f3fb0bb08a3
+F src/where.c 458b6e0d5e3e4eaaf75e352a88641ab2d7e21cad
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
 F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
@@ -797,7 +800,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P e7e7127f0b0db582274338a9fefc30a0c0be07c3
-R 169f65701c60c914b5babe14af8a5a2d
-U dan
-Z 59ba641787a7f590bcc552c76de3273b
+P 012cf101bf8be9e39c138786ea5a5039b8131e55
+R e6913462c9fc35ffdd8fb296dee81dc4
+U drh
+Z b112ddd6d5441568434e7011a246cd66
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQFLxhEcoxKgR168RlERAr4AAJ4o9PzYb8/4qM3TXJMcn3pTohzAyQCeOO2/
+T96saJ5mGiq/UIbcA3uQVL0=
+=Qkym
+-----END PGP SIGNATURE-----
index 8176592c4b07ffb11b051618758565ab06c63fc3..4577d98b848349d1b4ee2115b1ec76dea05b79ec 100644 (file)
@@ -1 +1 @@
-012cf101bf8be9e39c138786ea5a5039b8131e55
\ No newline at end of file
+b87cb0c2bd9c52a938795a974e101879b81210e3
\ No newline at end of file
index 3a06cb05ec6f67a1ce3d42e0802fa8204f69ea9a..f9fc477770aeed176f47ea743ede38e36364fc5c 100644 (file)
@@ -2601,10 +2601,10 @@ static void bestBtreeIndex(
     int nBound = 100;
     int bSort = 0;
     int bLookup = 0;
+    WhereTerm *pTerm;           /* A single term of the WHERE clause */
 
     /* Determine the values of nEq and nInMul */
     for(nEq=0; nEq<pProbe->nColumn; nEq++){
-      WhereTerm *pTerm;           /* A single term of the WHERE clause */
       int j = pProbe->aiColumn[nEq];
       pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx);
       if( pTerm==0 ) break;
@@ -2685,8 +2685,7 @@ static void bestBtreeIndex(
       }
     }
 
-    /**** Begin adding up the cost of using this index (Needs improvements)
-    **
+    /*
     ** Estimate the number of rows of output.  For an IN operator,
     ** do not let the estimate exceed half the rows in the table.
     */
@@ -2723,6 +2722,38 @@ static void bestBtreeIndex(
     }
     /**** Cost of using this index has now been computed ****/
 
+    /* If there are additional constraints on this table that cannot
+    ** be used with the current index, but which might lower the number
+    ** of output rows, adjust the nRow value accordingly.  This only 
+    ** matters if the current index is the least costly, so do not bother
+    ** with this step if we already know this index will not be chosen.
+    */
+    if( nRow>2 && cost<=pCost->rCost ){
+      int k;
+      int nSkip = nEq;
+      Bitmask thisTab = getMask(pWC->pMaskSet, iCur);
+      for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){
+        if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
+        if( (pTerm->prereqAll & notReady)!=thisTab ) continue;
+        if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
+          if( nSkip ){
+            /* Ignore the first nEq equality matches since the index
+            ** has already accounted for these */
+            nSkip--;
+          }else{
+            /* Assume each additional equality match reduces the result
+            ** set size by a factor of 10 */
+            nRow /= 10;
+          }
+        }else{
+          /* Any other expression lowers the output row count by half */
+          nRow /= 2;
+        }
+      }
+      if( nRow<2 ) nRow = 2;
+    }
+
+
     WHERETRACE((
       "%s(%s): nEq=%d nInMul=%d nBound=%d bSort=%d bLookup=%d wsFlags=0x%x\n"
       "         notReady=0x%llx nRow=%.2f cost=%.2f used=0x%llx\n",
@@ -2733,7 +2764,9 @@ static void bestBtreeIndex(
     /* If this index is the best we have seen so far, then record this
     ** index and its cost in the pCost structure.
     */
-    if( (!pIdx || wsFlags) && cost<pCost->rCost ){
+    if( (!pIdx || wsFlags)
+     && (cost<pCost->rCost || (cost==pCost->rCost && nRow<pCost->nRow))
+    ){
       pCost->rCost = cost;
       pCost->nRow = nRow;
       pCost->used = used;
@@ -2768,7 +2801,8 @@ static void bestBtreeIndex(
   );
 
   WHERETRACE(("best index is: %s\n", 
-    (pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
+    ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" : 
+         pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
   ));
   
   bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
@@ -4042,7 +4076,8 @@ WhereInfo *sqlite3WhereBegin(
         assert( isOptimal || (sCost.used&notReady)==0 );
 
         if( (sCost.used&notReady)==0
-         && (j==iFrom || sCost.rCost<bestPlan.rCost) 
+         && (j==iFrom || sCost.rCost<bestPlan.rCost
+             || (sCost.rCost==bestPlan.rCost && sCost.nRow<bestPlan.nRow))
         ){
           bestPlan = sCost;
           bestJ = j;