aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2014-08-07 16:50:00 +0000
committerdrh <drh@noemail.net>2014-08-07 16:50:00 +0000
commitddef5dc044de3ec73c9223359d45f1a6a55a792d (patch)
treee882b89d18b3ce6e5431144ceeeef2081227dc9e /src
parent858b638d1f76b0bb1a7f47f3eab72ca69a3a587e (diff)
downloadsqlite-ddef5dc044de3ec73c9223359d45f1a6a55a792d.tar.gz
sqlite-ddef5dc044de3ec73c9223359d45f1a6a55a792d.zip
When the estimated cost to do a sort overwhelms the estimated cost to do
individual table lookups, make sure that the table lookup costs are still taken into consideration when selecting the lookup algorithm. FossilOrigin-Name: ec5d84ba69c100d9565425ed74040a49e410ea03
Diffstat (limited to 'src')
-rw-r--r--src/where.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/src/where.c b/src/where.c
index 20823046f..ff65cc3b3 100644
--- a/src/where.c
+++ b/src/where.c
@@ -5424,6 +5424,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
LogEst rCost; /* Cost of a path */
LogEst nOut; /* Number of outputs */
LogEst mxCost = 0; /* Maximum cost of a set of paths */
+ LogEst mxOut = 0; /* nOut value for maximum cost path */
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
WherePath *aFrom; /* All nFrom paths at the previous level */
WherePath *aTo; /* The nTo best paths at the current level */
@@ -5441,7 +5442,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
** For joins of 3 or more tables, track the 10 best paths */
mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
assert( nLoop<=pWInfo->pTabList->nSrc );
- WHERETRACE(0x002, ("---- begin solver\n"));
+ WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst));
/* Allocate and initialize space for aTo and aFrom */
ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
@@ -5529,7 +5530,13 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
}else{
revMask = pFrom->revLoop;
}
- /* Check to see if pWLoop should be added to the mxChoice best so far */
+ /* Check to see if pWLoop should be added to the set of
+ ** mxChoice best-so-far paths.
+ **
+ ** First look for an existing path among best-so-far paths
+ ** that covers the same set of loops and has the same isOrdered
+ ** setting as the current path candidate.
+ */
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
if( pTo->maskLoop==maskNew
&& ((pTo->isOrdered^isOrdered)&80)==0
@@ -5539,7 +5546,14 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
}
}
if( jj>=nTo ){
- if( nTo>=mxChoice && rCost>=mxCost ){
+ /* None of the existing best-so-far paths match the candidate. */
+if( nTo>=mxChoice && rCost==mxCost ) printf("nOut=%d mxOut=%d\n", nOut, mxOut);
+ if( nTo>=mxChoice
+ && (rCost>mxCost || (rCost==mxCost && nOut>=mxOut))
+ ){
+ /* The current candidate is no better than any of the mxChoice
+ ** paths currently in the best-so-far buffer. So discard
+ ** this candidate as not viable. */
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
@@ -5549,7 +5563,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#endif
continue;
}
- /* Add a new Path to the aTo[] set */
+ /* If we reach this points it means that the new candidate path
+ ** needs to be added to the set of best-so-far paths. */
if( nTo<mxChoice ){
/* Increase the size of the aTo set by one */
jj = nTo++;
@@ -5566,7 +5581,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
}
#endif
}else{
- if( pTo->rCost<=rCost ){
+ /* Control reaches here if best-so-far path pTo=aTo[jj] covers the
+ ** same set of loops and has the sam isOrdered setting as the
+ ** candidate path. Check to see if the candidate should replace
+ ** pTo or if the candidate should be skipped */
+ if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
@@ -5578,11 +5597,13 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
+ /* Discard the candidate path from further consideration */
testcase( pTo->rCost==rCost );
continue;
}
testcase( pTo->rCost==rCost+1 );
- /* A new and better score for a previously created equivalent path */
+ /* Control reaches here if the candidate path is better than the
+ ** pTo path. Replace pTo with the candidate. */
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
@@ -5606,9 +5627,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( nTo>=mxChoice ){
mxI = 0;
mxCost = aTo[0].rCost;
+ mxOut = aTo[0].nRow;
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
- if( pTo->rCost>mxCost ){
+ if( pTo->rCost>mxCost || (pTo->rCost==mxCost && pTo->nRow>mxOut) ){
mxCost = pTo->rCost;
+ mxOut = pTo->nRow;
mxI = jj;
}
}