From: drh Date: Wed, 14 Apr 2010 19:01:44 +0000 (+0000) Subject: The query planner uses non-indexable WHERE clause terms to reduce the X-Git-Tag: version-3.7.2~470 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1e0f4a83d69a2eaa8fd334478a014d2a741a1aee;p=thirdparty%2Fsqlite.git The query planner uses non-indexable WHERE clause terms to reduce the estimated number of output rows, then uses the estimated number of output rows as a tie-breaker when choosing table order. FossilOrigin-Name: b87cb0c2bd9c52a938795a974e101879b81210e3 --- diff --git a/manifest b/manifest index 0092203951..552af60972 100644 --- 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----- diff --git a/manifest.uuid b/manifest.uuid index 8176592c4b..4577d98b84 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -012cf101bf8be9e39c138786ea5a5039b8131e55 \ No newline at end of file +b87cb0c2bd9c52a938795a974e101879b81210e3 \ No newline at end of file diff --git a/src/where.c b/src/where.c index 3a06cb05ec..f9fc477770 100644 --- a/src/where.c +++ b/src/where.c @@ -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; nEqnColumn; 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) && costrCost ){ + if( (!pIdx || wsFlags) + && (costrCost || (cost==pCost->rCost && nRownRow)) + ){ 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¬Ready)==0 ); if( (sCost.used¬Ready)==0 - && (j==iFrom || sCost.rCost