diff options
author | drh <drh@noemail.net> | 2020-02-22 16:58:49 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2020-02-22 16:58:49 +0000 |
commit | 89efac94fdfac50fac7f971edbde4850b008ecd8 (patch) | |
tree | 31c604c5185e1d8afb51010ec7abe8ad9bc71334 /src | |
parent | e8c4f03266e1b89bc693c2294734c4f828a177f8 (diff) | |
download | sqlite-89efac94fdfac50fac7f971edbde4850b008ecd8.tar.gz sqlite-89efac94fdfac50fac7f971edbde4850b008ecd8.zip |
When stat4 information is available, try to use it to improve the truth
probability of WHERE clause terms that do not participate in the index.
FossilOrigin-Name: 1babd6ec5d60e2c34aa1c0285ead768a88004218468e97262411973fe3487022
Diffstat (limited to 'src')
-rw-r--r-- | src/where.c | 47 | ||||
-rw-r--r-- | src/whereInt.h | 10 |
2 files changed, 49 insertions, 8 deletions
diff --git a/src/where.c b/src/where.c index da9c5a723..58cf11ab1 100644 --- a/src/where.c +++ b/src/where.c @@ -2307,7 +2307,10 @@ static void whereLoopOutputAdjust( }else{ k = 20; } - if( iReduce<k ) iReduce = k; + if( iReduce<k ){ + pTerm->wtFlags |= TERM_HEURTRUTH; + iReduce = k; + } } } } @@ -2489,9 +2492,9 @@ static int whereLoopAddBtreeIndex( } if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ - pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE; + pBuilder->bldFlags1 |= SQLITE_BLDF1_UNIQUE; }else{ - pBuilder->bldFlags |= SQLITE_BLDF_INDEXED; + pBuilder->bldFlags1 |= SQLITE_BLDF1_INDEXED; } pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; @@ -2656,6 +2659,21 @@ static int whereLoopAddBtreeIndex( if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */ if( nOut ){ pNew->nOut = sqlite3LogEst(nOut); + if( nEq==1 && pTerm->truthProb>0 ){ +#if WHERETRACE_ENABLED /* 0x01 */ + if( sqlite3WhereTrace & 0x01 ){ + sqlite3DebugPrintf("Update truthProb from %d to %d:\n", + pTerm->truthProb, pNew->nOut - pProbe->aiRowLogEst[0]); + sqlite3WhereTermPrint(pTerm, 999); + } +#endif + pTerm->truthProb = pNew->nOut - pProbe->aiRowLogEst[0]; + if( pTerm->wtFlags & TERM_HEURTRUTH ){ + /* If the old heuristic truthProb was previously used, signal + ** that all loops will need to be recomputed */ + pBuilder->bldFlags2 |= SQLITE_BLDF2_2NDPASS; + } + } if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut; pNew->nOut -= nIn; } @@ -3080,9 +3098,9 @@ static int whereLoopAddBtree( } } - pBuilder->bldFlags = 0; + pBuilder->bldFlags1 = 0; rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); - if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){ + if( pBuilder->bldFlags1==SQLITE_BLDF1_INDEXED ){ /* If a non-unique index is used, or if a prefix of the key for ** unique index is used (making the index functionally non-unique) ** then the sqlite_stat1 data becomes important for scoring the @@ -4838,6 +4856,25 @@ WhereInfo *sqlite3WhereBegin( if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ rc = whereLoopAddAll(&sWLB); if( rc ) goto whereBeginError; + +#ifdef SQLITE_ENABLE_STAT4 + /* If one or more WhereTerm.truthProb values were used in estimating + ** loop parameters, but then those truthProb values were subsequently + ** changed based on STAT4 information while computing subsequent loops, + ** then we need to rerun the whole loop building process so that all + ** loops will be built using the revised truthProb values. */ + if( sWLB.bldFlags2 & SQLITE_BLDF2_2NDPASS ){ + WHERETRACE(0xffff, + ("**** Redo all loop computations due to truthProb changes ****\n")); + while( pWInfo->pLoops ){ + WhereLoop *p = pWInfo->pLoops; + pWInfo->pLoops = p->pNextLoop; + whereLoopDelete(db, p); + } + rc = whereLoopAddAll(&sWLB); + if( rc ) goto whereBeginError; + } +#endif #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */ diff --git a/src/whereInt.h b/src/whereInt.h index 74101624d..9d4559c74 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -291,6 +291,7 @@ struct WhereTerm { #define TERM_LIKE 0x0400 /* The original LIKE operator */ #define TERM_IS 0x0800 /* Term.pExpr is an IS operator */ #define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */ +#define TERM_HEURTRUTH 0x2000 /* Heuristic truthProb used */ /* ** An instance of the WhereScan object is used as an iterator for locating @@ -405,13 +406,16 @@ struct WhereLoopBuilder { UnpackedRecord *pRec; /* Probe for stat4 (if required) */ int nRecValid; /* Number of valid fields currently in pRec */ #endif - unsigned int bldFlags; /* SQLITE_BLDF_* flags */ + unsigned char bldFlags1; /* First set of SQLITE_BLDF_* flags */ + unsigned char bldFlags2; /* Second set of SQLITE_BLDF_* flags */ unsigned int iPlanLimit; /* Search limiter */ }; /* Allowed values for WhereLoopBuider.bldFlags */ -#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */ -#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ +#define SQLITE_BLDF1_INDEXED 0x0001 /* An index is used */ +#define SQLITE_BLDF1_UNIQUE 0x0002 /* All keys of a UNIQUE index used */ + +#define SQLITE_BLDF2_2NDPASS 0x0004 /* Second builder pass needed */ /* The WhereLoopBuilder.iPlanLimit is used to limit the number of ** index+constraint combinations the query planner will consider for a |