mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-18 10:21:03 +03:00
Deploy heuristics (well-commented) to better estimate how much unindexed terms
in the WHERE clause filter the number of output rows from a single table. FossilOrigin-Name: 221659945c3f78d3b6789bfe8fdeb8d3ee1fa038
This commit is contained in:
52
src/where.c
52
src/where.c
@@ -4291,10 +4291,30 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
||||
** Adjust the WhereLoop.nOut value downward to account for terms of the
|
||||
** WHERE clause that reference the loop but which are not used by an
|
||||
** index.
|
||||
*
|
||||
** For every WHERE clause term that is not used by the index
|
||||
** and which has a truth probability assigned by one of the likelihood(),
|
||||
** likely(), or unlikely() SQL functions, reduce the estimated number
|
||||
** of output rows by the probability specified.
|
||||
**
|
||||
** In the current implementation, the first extra WHERE clause term reduces
|
||||
** the number of output rows by a factor of 10 and each additional term
|
||||
** reduces the number of output rows by sqrt(2).
|
||||
** TUNING: For every WHERE clause term that is not used by the index
|
||||
** and which does not have an assigned truth probability, heuristics
|
||||
** described below are used to try to estimate the truth probability.
|
||||
** TODO --> Perhaps this is something that could be improved by better
|
||||
** table statistics.
|
||||
**
|
||||
** Heuristic 1: Estimate the truth probability as 6.25%. The 6.25%
|
||||
** value corresponds to 1 in LogEst notation, so this means decrement
|
||||
** the WhereLoop.nOut field for every such WHERE clause term.
|
||||
**
|
||||
** Heuristic 2: If there exists one or more WHERE clause terms of the
|
||||
** form "x==EXPR" and EXPR is not a constant 0 or 1, then make sure the
|
||||
** final output row estimate is no greater than 1/4 of the total number
|
||||
** of rows in the table. In other words, assume that x==EXPR will filter
|
||||
** out at least 3 out of 4 rows. If EXPR is -1 or 0 or 1, then maybe the
|
||||
** "x" column is boolean or else -1 or 0 or 1 is a common default value
|
||||
** on the "x" column and so in that case only cap the output row estimate
|
||||
** at 1/2 instead of 1/4.
|
||||
*/
|
||||
static void whereLoopOutputAdjust(
|
||||
WhereClause *pWC, /* The WHERE clause */
|
||||
@@ -4303,8 +4323,8 @@ static void whereLoopOutputAdjust(
|
||||
){
|
||||
WhereTerm *pTerm, *pX;
|
||||
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
|
||||
int i, j;
|
||||
int nEq = 0; /* Number of = constraints not within likely()/unlikely() */
|
||||
int i, j, k;
|
||||
LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */
|
||||
|
||||
assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
|
||||
for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
|
||||
@@ -4319,20 +4339,26 @@ static void whereLoopOutputAdjust(
|
||||
}
|
||||
if( j<0 ){
|
||||
if( pTerm->truthProb<=0 ){
|
||||
/* If a truth probability is specified using the likelihood() hints,
|
||||
** then use the probability provided by the application. */
|
||||
pLoop->nOut += pTerm->truthProb;
|
||||
}else{
|
||||
/* In the absence of explicit truth probabilities, use heuristics to
|
||||
** guess a reasonable truth probability. */
|
||||
pLoop->nOut--;
|
||||
if( pTerm->eOperator&WO_EQ ) nEq++;
|
||||
if( pTerm->eOperator&WO_EQ ){
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
|
||||
k = 10;
|
||||
}else{
|
||||
k = 20;
|
||||
}
|
||||
if( iReduce<k ) iReduce = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* TUNING: If there is at least one equality constraint in the WHERE
|
||||
** clause that does not have a likelihood() explicitly assigned to it
|
||||
** then do not let the estimated number of output rows exceed half
|
||||
** the number of rows in the table. */
|
||||
if( nEq && pLoop->nOut>nRow-10 ){
|
||||
pLoop->nOut = nRow - 10;
|
||||
}
|
||||
if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user