mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Begin an experimental refactoring to estimate the average number of bytes
in table and index rows and to use that information in query planner. Begin by renaming WhereCost to LogEst and making that type and its conversion routines available outside of where.c. FossilOrigin-Name: 66c4a251d61582b47d5cbe50cbca160a9209bd06
This commit is contained in:
231
src/where.c
231
src/where.c
@@ -48,26 +48,6 @@ typedef struct WhereScan WhereScan;
|
||||
typedef struct WhereOrCost WhereOrCost;
|
||||
typedef struct WhereOrSet WhereOrSet;
|
||||
|
||||
/*
|
||||
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The
|
||||
** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
|
||||
** (Virtual tables can return a larger cost, but let's assume they do not.)
|
||||
** So all costs can be stored in a 16-bit integer without risk
|
||||
** of overflow.
|
||||
**
|
||||
** Costs are estimates, so no effort is made to compute 10*log2(X) exactly.
|
||||
** Instead, a close estimate is used. Any value of X=1 is stored as 0.
|
||||
** X=2 is 10. X=3 is 16. X=1000 is 99. etc. Negative values are allowed.
|
||||
** A WhereCost of -10 means 0.5. WhereCost of -20 means 0.25. And so forth.
|
||||
**
|
||||
** The tool/wherecosttest.c source file implements a command-line program
|
||||
** that will convert WhereCosts to integers, convert integers to WhereCosts
|
||||
** and do addition and multiplication on WhereCost values. The wherecosttest
|
||||
** command-line program is a useful utility to have around when working with
|
||||
** this module.
|
||||
*/
|
||||
typedef short int WhereCost;
|
||||
|
||||
/*
|
||||
** This object contains information needed to implement a single nested
|
||||
** loop in WHERE clause.
|
||||
@@ -132,9 +112,9 @@ struct WhereLoop {
|
||||
#endif
|
||||
u8 iTab; /* Position in FROM clause of table for this loop */
|
||||
u8 iSortIdx; /* Sorting index number. 0==None */
|
||||
WhereCost rSetup; /* One-time setup cost (ex: create transient index) */
|
||||
WhereCost rRun; /* Cost of running each loop */
|
||||
WhereCost nOut; /* Estimated number of output rows */
|
||||
LogEst rSetup; /* One-time setup cost (ex: create transient index) */
|
||||
LogEst rRun; /* Cost of running each loop */
|
||||
LogEst nOut; /* Estimated number of output rows */
|
||||
union {
|
||||
struct { /* Information for internal btree tables */
|
||||
int nEq; /* Number of equality constraints */
|
||||
@@ -164,8 +144,8 @@ struct WhereLoop {
|
||||
*/
|
||||
struct WhereOrCost {
|
||||
Bitmask prereq; /* Prerequisites */
|
||||
WhereCost rRun; /* Cost of running this subquery */
|
||||
WhereCost nOut; /* Number of outputs for this subquery */
|
||||
LogEst rRun; /* Cost of running this subquery */
|
||||
LogEst nOut; /* Number of outputs for this subquery */
|
||||
};
|
||||
|
||||
/* The WhereOrSet object holds a set of possible WhereOrCosts that
|
||||
@@ -203,8 +183,8 @@ static int whereLoopResize(sqlite3*, WhereLoop*, int);
|
||||
struct WherePath {
|
||||
Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
|
||||
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
|
||||
WhereCost nRow; /* Estimated number of rows generated by this path */
|
||||
WhereCost rCost; /* Total cost of this path */
|
||||
LogEst nRow; /* Estimated number of rows generated by this path */
|
||||
LogEst rCost; /* Total cost of this path */
|
||||
u8 isOrdered; /* True if this path satisfies ORDER BY */
|
||||
u8 isOrderedValid; /* True if the isOrdered field is valid */
|
||||
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
|
||||
@@ -270,7 +250,7 @@ struct WhereTerm {
|
||||
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
|
||||
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
|
||||
} u;
|
||||
WhereCost truthProb; /* Probability of truth for this expression */
|
||||
LogEst truthProb; /* Probability of truth for this expression */
|
||||
u16 eOperator; /* A WO_xx value describing <op> */
|
||||
u8 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u8 nChild; /* Number of children that must disable us */
|
||||
@@ -418,7 +398,7 @@ struct WhereInfo {
|
||||
ExprList *pResultSet; /* Result set. DISTINCT operates on these */
|
||||
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
||||
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
||||
WhereCost nRowOut; /* Estimated number of output rows */
|
||||
LogEst nRowOut; /* Estimated number of output rows */
|
||||
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
|
||||
u8 bOBSat; /* ORDER BY satisfied by indices */
|
||||
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
|
||||
@@ -478,26 +458,11 @@ struct WhereInfo {
|
||||
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
|
||||
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
|
||||
|
||||
|
||||
/* Convert a WhereCost value (10 times log2(X)) into its integer value X.
|
||||
** A rough approximation is used. The value returned is not exact.
|
||||
*/
|
||||
static u64 whereCostToInt(WhereCost x){
|
||||
u64 n;
|
||||
if( x<10 ) return 1;
|
||||
n = x%10;
|
||||
x /= 10;
|
||||
if( n>=5 ) n -= 2;
|
||||
else if( n>=1 ) n -= 1;
|
||||
if( x>=3 ) return (n+8)<<(x-3);
|
||||
return (n+8)>>(3-x);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the estimated number of output rows from a WHERE clause
|
||||
*/
|
||||
u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
|
||||
return whereCostToInt(pWInfo->nRowOut);
|
||||
return sqlite3LogEstToInt(pWInfo->nRowOut);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -559,8 +524,8 @@ static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
|
||||
static int whereOrInsert(
|
||||
WhereOrSet *pSet, /* The WhereOrSet to be updated */
|
||||
Bitmask prereq, /* Prerequisites of the new entry */
|
||||
WhereCost rRun, /* Run-cost of the new entry */
|
||||
WhereCost nOut /* Number of outputs for the new entry */
|
||||
LogEst rRun, /* Run-cost of the new entry */
|
||||
LogEst nOut /* Number of outputs for the new entry */
|
||||
){
|
||||
u16 i;
|
||||
WhereOrCost *p;
|
||||
@@ -645,9 +610,6 @@ static void whereClauseClear(WhereClause *pWC){
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static WhereCost whereCost(tRowcnt x);
|
||||
|
||||
/*
|
||||
** Add a single new WhereTerm entry to the WhereClause object pWC.
|
||||
** The new WhereTerm object is constructed from Expr p and with wtFlags.
|
||||
@@ -690,7 +652,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
|
||||
}
|
||||
pTerm = &pWC->a[idx = pWC->nTerm++];
|
||||
if( p && ExprHasProperty(p, EP_Unlikely) ){
|
||||
pTerm->truthProb = whereCost(p->iTable) - 99;
|
||||
pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
|
||||
}else{
|
||||
pTerm->truthProb = -1;
|
||||
}
|
||||
@@ -1954,75 +1916,12 @@ static int isDistinctRedundant(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Find (an approximate) sum of two WhereCosts. This computation is
|
||||
** not a simple "+" operator because WhereCost is stored as a logarithmic
|
||||
** value.
|
||||
**
|
||||
*/
|
||||
static WhereCost whereCostAdd(WhereCost a, WhereCost b){
|
||||
static const unsigned char x[] = {
|
||||
10, 10, /* 0,1 */
|
||||
9, 9, /* 2,3 */
|
||||
8, 8, /* 4,5 */
|
||||
7, 7, 7, /* 6,7,8 */
|
||||
6, 6, 6, /* 9,10,11 */
|
||||
5, 5, 5, /* 12-14 */
|
||||
4, 4, 4, 4, /* 15-18 */
|
||||
3, 3, 3, 3, 3, 3, /* 19-24 */
|
||||
2, 2, 2, 2, 2, 2, 2, /* 25-31 */
|
||||
};
|
||||
if( a>=b ){
|
||||
if( a>b+49 ) return a;
|
||||
if( a>b+31 ) return a+1;
|
||||
return a+x[a-b];
|
||||
}else{
|
||||
if( b>a+49 ) return b;
|
||||
if( b>a+31 ) return b+1;
|
||||
return b+x[b-a];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert an integer into a WhereCost. In other words, compute a
|
||||
** good approximatation for 10*log2(x).
|
||||
*/
|
||||
static WhereCost whereCost(tRowcnt x){
|
||||
static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
|
||||
WhereCost y = 40;
|
||||
if( x<8 ){
|
||||
if( x<2 ) return 0;
|
||||
while( x<8 ){ y -= 10; x <<= 1; }
|
||||
}else{
|
||||
while( x>255 ){ y += 40; x >>= 4; }
|
||||
while( x>15 ){ y += 10; x >>= 1; }
|
||||
}
|
||||
return a[x&7] + y - 10;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
** Convert a double (as received from xBestIndex of a virtual table)
|
||||
** into a WhereCost. In other words, compute an approximation for
|
||||
** 10*log2(x).
|
||||
*/
|
||||
static WhereCost whereCostFromDouble(double x){
|
||||
u64 a;
|
||||
WhereCost e;
|
||||
assert( sizeof(x)==8 && sizeof(a)==8 );
|
||||
if( x<=1 ) return 0;
|
||||
if( x<=2000000000 ) return whereCost((tRowcnt)x);
|
||||
memcpy(&a, &x, 8);
|
||||
e = (a>>52) - 1022;
|
||||
return e*10;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
/*
|
||||
** Estimate the logarithm of the input value to base 2.
|
||||
*/
|
||||
static WhereCost estLog(WhereCost N){
|
||||
WhereCost x = whereCost(N);
|
||||
static LogEst estLog(LogEst N){
|
||||
LogEst x = sqlite3LogEst(N);
|
||||
return x>33 ? x - 33 : 0;
|
||||
}
|
||||
|
||||
@@ -2535,7 +2434,7 @@ static void whereKeyStats(
|
||||
**
|
||||
** then nEq is set to 0.
|
||||
**
|
||||
** When this function is called, *pnOut is set to the whereCost() of the
|
||||
** When this function is called, *pnOut is set to the sqlite3LogEst() of the
|
||||
** number of rows that the index scan is expected to visit without
|
||||
** considering the range constraints. If nEq is 0, this is the number of
|
||||
** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
|
||||
@@ -2551,11 +2450,11 @@ static int whereRangeScanEst(
|
||||
WhereLoopBuilder *pBuilder,
|
||||
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
|
||||
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
|
||||
WhereCost *pnOut /* IN/OUT: Number of rows visited */
|
||||
LogEst *pnOut /* IN/OUT: Number of rows visited */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int nOut = (int)*pnOut;
|
||||
WhereCost nNew;
|
||||
LogEst nNew;
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
Index *p = pBuilder->pNew->u.btree.pIndex;
|
||||
@@ -2640,14 +2539,14 @@ static int whereRangeScanEst(
|
||||
pBuilder->pRec = pRec;
|
||||
if( rc==SQLITE_OK ){
|
||||
if( iUpper>iLower ){
|
||||
nNew = whereCost(iUpper - iLower);
|
||||
nNew = sqlite3LogEst(iUpper - iLower);
|
||||
}else{
|
||||
nNew = 10; assert( 10==whereCost(2) );
|
||||
nNew = 10; assert( 10==sqlite3LogEst(2) );
|
||||
}
|
||||
if( nNew<nOut ){
|
||||
nOut = nNew;
|
||||
}
|
||||
*pnOut = (WhereCost)nOut;
|
||||
*pnOut = (LogEst)nOut;
|
||||
WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
|
||||
(u32)iLower, (u32)iUpper, nOut));
|
||||
return SQLITE_OK;
|
||||
@@ -2662,16 +2561,16 @@ static int whereRangeScanEst(
|
||||
** A BETWEEN operator, therefore, reduces the search space 16-fold */
|
||||
nNew = nOut;
|
||||
if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
|
||||
nNew -= 20; assert( 20==whereCost(4) );
|
||||
nNew -= 20; assert( 20==sqlite3LogEst(4) );
|
||||
nOut--;
|
||||
}
|
||||
if( pUpper ){
|
||||
nNew -= 20; assert( 20==whereCost(4) );
|
||||
nNew -= 20; assert( 20==sqlite3LogEst(4) );
|
||||
nOut--;
|
||||
}
|
||||
if( nNew<10 ) nNew = 10;
|
||||
if( nNew<nOut ) nOut = nNew;
|
||||
*pnOut = (WhereCost)nOut;
|
||||
*pnOut = (LogEst)nOut;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -4315,7 +4214,7 @@ static int whereLoopAddBtreeIndex(
|
||||
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
|
||||
struct SrcList_item *pSrc, /* FROM clause term being analyzed */
|
||||
Index *pProbe, /* An index on pSrc */
|
||||
WhereCost nInMul /* log(Number of iterations due to IN) */
|
||||
LogEst nInMul /* log(Number of iterations due to IN) */
|
||||
){
|
||||
WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
|
||||
Parse *pParse = pWInfo->pParse; /* Parsing context */
|
||||
@@ -4328,11 +4227,11 @@ static int whereLoopAddBtreeIndex(
|
||||
u16 saved_nLTerm; /* Original value of pNew->nLTerm */
|
||||
int saved_nEq; /* Original value of pNew->u.btree.nEq */
|
||||
u32 saved_wsFlags; /* Original value of pNew->wsFlags */
|
||||
WhereCost saved_nOut; /* Original value of pNew->nOut */
|
||||
LogEst saved_nOut; /* Original value of pNew->nOut */
|
||||
int iCol; /* Index of the column in the table */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
WhereCost nRowEst; /* Estimated index selectivity */
|
||||
WhereCost rLogSize; /* Logarithm of table size */
|
||||
LogEst nRowEst; /* Estimated index selectivity */
|
||||
LogEst rLogSize; /* Logarithm of table size */
|
||||
WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
|
||||
|
||||
pNew = pBuilder->pNew;
|
||||
@@ -4352,7 +4251,7 @@ static int whereLoopAddBtreeIndex(
|
||||
assert( pNew->u.btree.nEq<=pProbe->nColumn );
|
||||
if( pNew->u.btree.nEq < pProbe->nColumn ){
|
||||
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
|
||||
nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
|
||||
nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
|
||||
if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
|
||||
}else{
|
||||
iCol = -1;
|
||||
@@ -4366,7 +4265,7 @@ static int whereLoopAddBtreeIndex(
|
||||
saved_prereq = pNew->prereq;
|
||||
saved_nOut = pNew->nOut;
|
||||
pNew->rSetup = 0;
|
||||
rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
|
||||
rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
|
||||
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
|
||||
int nIn = 0;
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
@@ -4393,10 +4292,10 @@ static int whereLoopAddBtreeIndex(
|
||||
pNew->wsFlags |= WHERE_COLUMN_IN;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
|
||||
nIn = 46; assert( 46==whereCost(25) );
|
||||
nIn = 46; assert( 46==sqlite3LogEst(25) );
|
||||
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
|
||||
/* "x IN (value, value, ...)" */
|
||||
nIn = whereCost(pExpr->x.pList->nExpr);
|
||||
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
|
||||
}
|
||||
pNew->rRun += nIn;
|
||||
pNew->u.btree.nEq++;
|
||||
@@ -4418,7 +4317,7 @@ static int whereLoopAddBtreeIndex(
|
||||
pNew->wsFlags |= WHERE_COLUMN_NULL;
|
||||
pNew->u.btree.nEq++;
|
||||
/* TUNING: IS NULL selects 2 rows */
|
||||
nIn = 10; assert( 10==whereCost(2) );
|
||||
nIn = 10; assert( 10==sqlite3LogEst(2) );
|
||||
pNew->nOut = nRowEst + nInMul + nIn;
|
||||
}else if( pTerm->eOperator & (WO_GT|WO_GE) ){
|
||||
testcase( pTerm->eOperator & WO_GT );
|
||||
@@ -4458,7 +4357,7 @@ static int whereLoopAddBtreeIndex(
|
||||
}
|
||||
assert( nOut==0 || rc==SQLITE_OK );
|
||||
if( nOut ){
|
||||
nOut = whereCost(nOut);
|
||||
nOut = sqlite3LogEst(nOut);
|
||||
pNew->nOut = MIN(nOut, saved_nOut);
|
||||
}
|
||||
}
|
||||
@@ -4466,10 +4365,10 @@ static int whereLoopAddBtreeIndex(
|
||||
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
|
||||
/* Each row involves a step of the index, then a binary search of
|
||||
** the main table */
|
||||
pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10);
|
||||
}
|
||||
/* Step cost for each output row */
|
||||
pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
|
||||
whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
|
||||
rc = whereLoopInsert(pBuilder, pNew);
|
||||
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
|
||||
@@ -4569,8 +4468,8 @@ static int whereLoopAddBtree(
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
int iSortIdx = 1; /* Index number */
|
||||
int b; /* A boolean value */
|
||||
WhereCost rSize; /* number of rows in the table */
|
||||
WhereCost rLogSize; /* Logarithm of the number of rows in the table */
|
||||
LogEst rSize; /* number of rows in the table */
|
||||
LogEst rLogSize; /* Logarithm of the number of rows in the table */
|
||||
WhereClause *pWC; /* The parsed WHERE clause */
|
||||
|
||||
pNew = pBuilder->pNew;
|
||||
@@ -4605,7 +4504,7 @@ static int whereLoopAddBtree(
|
||||
}
|
||||
pProbe = &sPk;
|
||||
}
|
||||
rSize = whereCost(pSrc->pTab->nRowEst);
|
||||
rSize = sqlite3LogEst(pSrc->pTab->nRowEst);
|
||||
rLogSize = estLog(rSize);
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
@@ -4630,13 +4529,13 @@ static int whereLoopAddBtree(
|
||||
/* TUNING: One-time cost for computing the automatic index is
|
||||
** approximately 7*N*log2(N) where N is the number of rows in
|
||||
** the table being indexed. */
|
||||
pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) );
|
||||
pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
|
||||
/* TUNING: Each index lookup yields 20 rows in the table. This
|
||||
** is more than the usual guess of 10 rows, since we have no way
|
||||
** of knowning how selective the index will ultimately be. It would
|
||||
** not be unreasonable to make this value much larger. */
|
||||
pNew->nOut = 43; assert( 43==whereCost(20) );
|
||||
pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
|
||||
pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
|
||||
pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
|
||||
pNew->wsFlags = WHERE_AUTO_INDEX;
|
||||
pNew->prereq = mExtra | pTerm->prereqRight;
|
||||
rc = whereLoopInsert(pBuilder, pNew);
|
||||
@@ -4669,9 +4568,9 @@ static int whereLoopAddBtree(
|
||||
/* Full table scan */
|
||||
pNew->iSortIdx = b ? iSortIdx : 0;
|
||||
/* TUNING: Cost of full table scan is 3*(N + log2(N)).
|
||||
** + The extra 4 factor is to encourage the use of indexed lookups
|
||||
** + The extra 3 factor is to encourage the use of indexed lookups
|
||||
** over full scans. */
|
||||
pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
|
||||
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
|
||||
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
|
||||
rc = whereLoopInsert(pBuilder, pNew);
|
||||
pNew->nOut = rSize;
|
||||
@@ -4693,11 +4592,11 @@ static int whereLoopAddBtree(
|
||||
pNew->iSortIdx = b ? iSortIdx : 0;
|
||||
if( m==0 ){
|
||||
/* TUNING: Cost of a covering index scan is K*(N + log2(N)).
|
||||
** + The extra factor K of between 1.0 and 3.0 is added to
|
||||
** encourage the use of indexed lookups. The value of K
|
||||
** depends on the iScanRatio value for the index.
|
||||
** + The extra factor K of between 1.1 (iScanRatio between 0
|
||||
** and 9) and 2.8 (iScanRatio between 126 and 127) is added
|
||||
** to encourage the use of indexed lookups.
|
||||
*/
|
||||
pNew->rRun = whereCostAdd(rSize,rLogSize) + pProbe->iScanRatio/9 + 1;
|
||||
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + pProbe->iScanRatio/9 + 1;
|
||||
}else{
|
||||
assert( b!=0 );
|
||||
/* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
|
||||
@@ -4875,9 +4774,9 @@ static int whereLoopAddVirtual(
|
||||
pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
|
||||
&& pIdxInfo->orderByConsumed);
|
||||
pNew->rSetup = 0;
|
||||
pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
|
||||
pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
|
||||
/* TUNING: Every virtual table query returns 25 rows */
|
||||
pNew->nOut = 46; assert( 46==whereCost(25) );
|
||||
pNew->nOut = 46; assert( 46==sqlite3LogEst(25) );
|
||||
whereLoopInsert(pBuilder, pNew);
|
||||
if( pNew->u.vtab.needFree ){
|
||||
sqlite3_free(pNew->u.vtab.idxStr);
|
||||
@@ -4967,8 +4866,8 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
|
||||
for(i=0; i<sPrev.n; i++){
|
||||
for(j=0; j<sCur.n; j++){
|
||||
whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
|
||||
whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
|
||||
whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
|
||||
sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
|
||||
sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5306,7 +5205,7 @@ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
|
||||
** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
|
||||
** error occurs.
|
||||
*/
|
||||
static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
int mxChoice; /* Maximum number of simultaneous paths tracked */
|
||||
int nLoop; /* Number of terms in the join */
|
||||
Parse *pParse; /* Parsing context */
|
||||
@@ -5314,11 +5213,11 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
int iLoop; /* Loop counter over the terms of the join */
|
||||
int ii, jj; /* Loop counters */
|
||||
int mxI = 0; /* Index of next entry to replace */
|
||||
WhereCost rCost; /* Cost of a path */
|
||||
WhereCost nOut; /* Number of outputs */
|
||||
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 */
|
||||
LogEst rCost; /* Cost of a path */
|
||||
LogEst nOut; /* Number of outputs */
|
||||
LogEst mxCost = 0; /* Maximum cost of a set of paths */
|
||||
LogEst mxOut = 0; /* Maximum nOut value on the set of paths */
|
||||
LogEst rSortCost; /* Cost to do a sort */
|
||||
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 */
|
||||
@@ -5355,7 +5254,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
** TUNING: Do not let the number of iterations go above 25. If the cost
|
||||
** of computing an automatic index is not paid back within the first 25
|
||||
** rows, then do not use the automatic index. */
|
||||
aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) );
|
||||
aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
|
||||
nFrom = 1;
|
||||
|
||||
/* Precompute the cost of sorting the final result set, if the caller
|
||||
@@ -5385,8 +5284,8 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
|
||||
/* At this point, pWLoop is a candidate to be the next loop.
|
||||
** Compute its cost */
|
||||
rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rCost = whereCostAdd(rCost, pFrom->rCost);
|
||||
rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
|
||||
nOut = pFrom->nRow + pWLoop->nOut;
|
||||
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
|
||||
if( !isOrderedValid ){
|
||||
@@ -5400,7 +5299,7 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
case 0: /* No. pFrom+pWLoop will require a separate sort */
|
||||
isOrdered = 0;
|
||||
isOrderedValid = 1;
|
||||
rCost = whereCostAdd(rCost, rSortCost);
|
||||
rCost = sqlite3LogEstAdd(rCost, rSortCost);
|
||||
break;
|
||||
default: /* Cannot tell yet. Try again on the next iteration */
|
||||
break;
|
||||
@@ -5607,7 +5506,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
||||
pLoop->nLTerm = 1;
|
||||
pLoop->u.btree.nEq = 1;
|
||||
/* TUNING: Cost of a rowid lookup is 10 */
|
||||
pLoop->rRun = 33; /* 33==whereCost(10) */
|
||||
pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
|
||||
}else{
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
assert( pLoop->aLTermSpace==pLoop->aLTerm );
|
||||
@@ -5630,12 +5529,12 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
|
||||
pLoop->u.btree.nEq = j;
|
||||
pLoop->u.btree.pIndex = pIdx;
|
||||
/* TUNING: Cost of a unique index lookup is 15 */
|
||||
pLoop->rRun = 39; /* 39==whereCost(15) */
|
||||
pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( pLoop->wsFlags ){
|
||||
pLoop->nOut = (WhereCost)1;
|
||||
pLoop->nOut = (LogEst)1;
|
||||
pWInfo->a[0].pWLoop = pLoop;
|
||||
pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
|
||||
pWInfo->a[0].iTabCur = iCur;
|
||||
|
||||
Reference in New Issue
Block a user