1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-06 15:49:35 +03:00

Enhance the plan solver to take into account the number of output rows when

computing the set of paths to retain for the next cycle.

FossilOrigin-Name: 1a46a7242313da96420985fa52e1de3f84533e5b
This commit is contained in:
drh
2013-09-06 17:45:42 +00:00
parent cca9f3d291
commit fde1e6bc37
4 changed files with 46 additions and 36 deletions

View File

@@ -1,5 +1,5 @@
C Initial\simplementation\sof\sthe\sunlikely()\sSQL\sfunction\sused\sas\sa\shint\sto\nthe\squery\splanner. C Enhance\sthe\splan\ssolver\sto\stake\sinto\saccount\sthe\snumber\sof\soutput\srows\swhen\ncomputing\sthe\sset\sof\spaths\sto\sretain\sfor\sthe\snext\scycle.
D 2013-09-06T15:23:29.191 D 2013-09-06T17:45:42.446
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -214,7 +214,7 @@ F src/pragma.c 3aa3d8c8623b7b71c5b1bfb72dcc31fb0c25665f
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
F src/resolve.c 748618c3df7f37f2cd33c8834770b1e34f9b1185 F src/resolve.c 8a2b6b9a6487e6e5a23b8de571131ccce62a1ce0
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78 F src/select.c 9239586282bd146ec5843a2cde7d54cd7816cf78
F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747 F src/shell.c d920a891ca09b8bd262cced7fb0ab9d723f7a747
@@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
F src/where.c c9f8ae51797bebfbfa49b9e5bede6fc142b44262 F src/where.c ce16c689b9a199ffffd63745405214912e941e6f
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -1111,10 +1111,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
P 97b10e66e98e84755aa577f8da017bf1aea2056c P 036fc37a034093a4c6fc190633bd41c2b7230d77
R fcd7cd29a90a12a870cace66939b8877 R 3890bf7553bc1077426fb2f0e0259279
T *branch * unlikely-func
T *sym-unlikely-func *
T -sym-trunk *
U drh U drh
Z 2a30cee668099b5c8e0e2b447ac67feb Z 80a7432df4b498524e527dd8f32c240f

View File

@@ -1 +1 @@
036fc37a034093a4c6fc190633bd41c2b7230d77 1a46a7242313da96420985fa52e1de3f84533e5b

View File

@@ -705,7 +705,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pNC->nErr++; pNC->nErr++;
} }
}else{ }else{
pExpr->iTable = 100; pExpr->iTable = 75;
} }
} }
} }

View File

@@ -5306,8 +5306,11 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
sqlite3 *db; /* The database connection */ sqlite3 *db; /* The database connection */
int iLoop; /* Loop counter over the terms of the join */ int iLoop; /* Loop counter over the terms of the join */
int ii, jj; /* Loop counters */ int ii, jj; /* Loop counters */
int mxI = 0; /* Index of next entry to replace */
WhereCost rCost; /* Cost of a path */ WhereCost rCost; /* Cost of a path */
WhereCost nOut; /* Number of outputs */
WhereCost mxCost = 0; /* Maximum cost of a set of paths */ WhereCost mxCost = 0; /* Maximum cost of a set of paths */
WhereCost mxOut = 0; /* Maximum nOut value on the set of paths */
WhereCost rSortCost; /* Cost to do a sort */ WhereCost rSortCost; /* Cost to do a sort */
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
WherePath *aFrom; /* All nFrom paths at the previous level */ WherePath *aFrom; /* All nFrom paths at the previous level */
@@ -5377,6 +5380,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
** Compute its cost */ ** Compute its cost */
rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
rCost = whereCostAdd(rCost, pFrom->rCost); rCost = whereCostAdd(rCost, pFrom->rCost);
nOut = pFrom->nRow + pWLoop->nOut;
maskNew = pFrom->maskLoop | pWLoop->maskSelf; maskNew = pFrom->maskLoop | pWLoop->maskSelf;
if( !isOrderedValid ){ if( !isOrderedValid ){
switch( wherePathSatisfiesOrderBy(pWInfo, switch( wherePathSatisfiesOrderBy(pWInfo,
@@ -5399,17 +5403,23 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
} }
/* Check to see if pWLoop should be added to the mxChoice best so far */ /* Check to see if pWLoop should be added to the mxChoice best so far */
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){ for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
if( pTo->maskLoop==maskNew && pTo->isOrderedValid==isOrderedValid ){ if( pTo->maskLoop==maskNew
&& pTo->isOrderedValid==isOrderedValid
&& ((pTo->rCost<=rCost && pTo->nRow<=nOut) ||
(pTo->rCost>=rCost && pTo->nRow>=nOut))
){
testcase( jj==nTo-1 ); testcase( jj==nTo-1 );
break; break;
} }
} }
if( jj>=nTo ){ if( jj>=nTo ){
if( nTo>=mxChoice && rCost>=mxCost ){ if( nTo>=mxChoice
&& (rCost>mxCost || (rCost==mxCost && nOut>=mxOut))
){
#ifdef WHERETRACE_ENABLED #ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace&0x4 ){ if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("Skip %s cost=%3d order=%c\n", sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost, wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
} }
#endif #endif
@@ -5421,26 +5431,26 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
jj = nTo++; jj = nTo++;
}else{ }else{
/* New path replaces the prior worst to keep count below mxChoice */ /* New path replaces the prior worst to keep count below mxChoice */
for(jj=nTo-1; aTo[jj].rCost<mxCost; jj--){ assert(jj>0); } jj = mxI;
} }
pTo = &aTo[jj]; pTo = &aTo[jj];
#ifdef WHERETRACE_ENABLED #ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace&0x4 ){ if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("New %s cost=%-3d order=%c\n", sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n",
wherePathName(pFrom, iLoop, pWLoop), rCost, wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
} }
#endif #endif
}else{ }else{
if( pTo->rCost<=rCost ){ if( pTo->rCost<=rCost && pTo->nRow<=nOut ){
#ifdef WHERETRACE_ENABLED #ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace&0x4 ){ if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf( sqlite3DebugPrintf(
"Skip %s cost=%-3d order=%c", "Skip %s cost=%-3d,%3d order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost, wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
sqlite3DebugPrintf(" vs %s cost=%-3d order=%c\n", sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
} }
#endif #endif
@@ -5452,11 +5462,11 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
#ifdef WHERETRACE_ENABLED #ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace&0x4 ){ if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf( sqlite3DebugPrintf(
"Update %s cost=%-3d order=%c", "Update %s cost=%-3d,%3d order=%c",
wherePathName(pFrom, iLoop, pWLoop), rCost, wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
sqlite3DebugPrintf(" was %s cost=%-3d order=%c\n", sqlite3DebugPrintf(" was %s cost=%-3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
} }
#endif #endif
@@ -5464,16 +5474,22 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
/* pWLoop is a winner. Add it to the set of best so far */ /* pWLoop is a winner. Add it to the set of best so far */
pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf; pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
pTo->revLoop = revMask; pTo->revLoop = revMask;
pTo->nRow = pFrom->nRow + pWLoop->nOut; pTo->nRow = nOut;
pTo->rCost = rCost; pTo->rCost = rCost;
pTo->isOrderedValid = isOrderedValid; pTo->isOrderedValid = isOrderedValid;
pTo->isOrdered = isOrdered; pTo->isOrdered = isOrdered;
memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
pTo->aLoop[iLoop] = pWLoop; pTo->aLoop[iLoop] = pWLoop;
if( nTo>=mxChoice ){ if( nTo>=mxChoice ){
mxI = 0;
mxCost = aTo[0].rCost; mxCost = aTo[0].rCost;
mxOut = aTo[0].nRow;
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){ for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
if( pTo->rCost>mxCost ) mxCost = pTo->rCost; if( pTo->rCost>mxCost || (pTo->rCost==mxCost && pTo->nRow>mxOut) ){
mxCost = pTo->rCost;
mxOut = pTo->nRow;
mxI = jj;
}
} }
} }
} }
@@ -5510,12 +5526,9 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
/* Find the lowest cost path. pFrom will be left pointing to that path */ /* Find the lowest cost path. pFrom will be left pointing to that path */
pFrom = aFrom; pFrom = aFrom;
assert( nFrom==1 );
#if 0 /* The following is needed if nFrom is ever more than 1 */
for(ii=1; ii<nFrom; ii++){ for(ii=1; ii<nFrom; ii++){
if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
} }
#endif
assert( pWInfo->nLevel==nLoop ); assert( pWInfo->nLevel==nLoop );
/* Load the lowest cost path into pWInfo */ /* Load the lowest cost path into pWInfo */
for(iLoop=0; iLoop<nLoop; iLoop++){ for(iLoop=0; iLoop<nLoop; iLoop++){