aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2020-02-22 16:58:49 +0000
committerdrh <drh@noemail.net>2020-02-22 16:58:49 +0000
commit89efac94fdfac50fac7f971edbde4850b008ecd8 (patch)
tree31c604c5185e1d8afb51010ec7abe8ad9bc71334 /src
parente8c4f03266e1b89bc693c2294734c4f828a177f8 (diff)
downloadsqlite-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.c47
-rw-r--r--src/whereInt.h10
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