When estimating the cost of an index scan, factor in the cost savings of
being able to use the index to evaluate some WHERE clause terms without having to do a table lookup. FossilOrigin-Name: a59b5622f7cc6e502d71aabc12c053582cd03609
This commit is contained in:
parent
2900a6222f
commit
2409f8a112
21
manifest
21
manifest
@ -1,5 +1,5 @@
|
||||
C Ensure\sthat\sthe\ssqlite3_scrub_backup()\sextension\screates\sa\sbackup\sdatabase\sat\sleast\sas\slarge\sas\sindicated\sby\sthe\sdatabase\sheader,\seven\sif\sthe\slast\spage\sof\sthe\sinput\sdatabase\sis\sa\sfree-list\sleaf.
|
||||
D 2016-07-26T10:46:21.988
|
||||
C When\sestimating\sthe\scost\sof\san\sindex\sscan,\sfactor\sin\sthe\scost\ssavings\sof\nbeing\sable\sto\suse\sthe\sindex\sto\sevaluate\ssome\sWHERE\sclause\sterms\swithout\nhaving\sto\sdo\sa\stable\slookup.
|
||||
D 2016-07-27T18:27:02.556
|
||||
F Makefile.in 6c20d44f72d4564f11652b26291a214c8367e5db
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a
|
||||
@ -337,7 +337,7 @@ F src/ctime.c 61949e83c4c36e37195a8398ebc752780b534d95
|
||||
F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39
|
||||
F src/dbstat.c 4f6f7f52b49beb9636ffbd517cfe44a402ba4ad0
|
||||
F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f
|
||||
F src/expr.c 21b153e1046c624e9387a17d3261f69b461e700c
|
||||
F src/expr.c 3347e66d4e27ec5f3ec7573b9a5f899bbd7d1df8
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c bc4145347595b7770f9a598cff1c848302cf5413
|
||||
F src/func.c 61a4114cf7004f10c542cfabbab9f2bcb9033045
|
||||
@ -388,7 +388,7 @@ F src/shell.c 9351fc6de11e1d908648c0a92d85627138e3dee5
|
||||
F src/sqlite.h.in c6e68a4a47610631822a4f8f83a44c9f75339331
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 46f300b6e300e0fa916d7d58c44b53415b8471a9
|
||||
F src/sqliteInt.h 49081ceab08eda9943d555aee57392c5b35d1c60
|
||||
F src/sqliteInt.h d25c18c1272a7811e2569c39bfc2fca96156eead
|
||||
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
|
||||
F src/status.c 5b18f9526900f61189ab0b83f1ef41d9f871a2ab
|
||||
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
|
||||
@ -463,7 +463,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 02eeecc265f6ffd0597378f5d8ae9070b62a406a
|
||||
F src/wal.h 6dd221ed384afdc204bc61e25c23ef7fd5a511f2
|
||||
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
|
||||
F src/where.c 48eed8ebe319c6cbc7bf7682018f32af0f5189f5
|
||||
F src/where.c 7e4d676b5ac4434e5f93606a744d396dc40d9977
|
||||
F src/whereInt.h e5b939701a7ceffc5a3a8188a37f9746416ebcd0
|
||||
F src/wherecode.c 99707d11907c71d289ee9553d2d1a22f1fd8ba41
|
||||
F src/whereexpr.c d7dcbf14ce1b5876c1f76496162c30fcba669563
|
||||
@ -1507,7 +1507,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P c0e7d98ef2a13ede5ae865083ede1aaffdf43310
|
||||
R 783c6677056c1c6297ef166e24fadbce
|
||||
U dan
|
||||
Z 42a389186c57610d077ea553714cade1
|
||||
P 483994a54dee3c7a3801e0e9d3c96fa9dbd8d2fd
|
||||
R 9e4bd013f5c2cf2171d472668aed0d1c
|
||||
T *branch * improved-index-scan
|
||||
T *sym-improved-index-scan *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 8f3398744130761f466da0e8b7212fe4
|
||||
|
@ -1 +1 @@
|
||||
483994a54dee3c7a3801e0e9d3c96fa9dbd8d2fd
|
||||
a59b5622f7cc6e502d71aabc12c053582cd03609
|
55
src/expr.c
55
src/expr.c
@ -3965,6 +3965,61 @@ int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** An instance of the following structure is used by the tree walker
|
||||
** to determine if an expression can be evaluated by reference to the
|
||||
** index only, without having to do a search for the corresponding
|
||||
** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur
|
||||
** is the cursor for the table.
|
||||
*/
|
||||
struct IdxCover {
|
||||
Index *pIdx; /* The index to be tested for coverage */
|
||||
int iCur; /* Cursor number for the table corresponding to the index */
|
||||
};
|
||||
|
||||
/*
|
||||
** Check to see if there are references to columns in table
|
||||
** pWalker->u.pIdxCover->iCur can be satisfied using the index
|
||||
** pWalker->u.pIdxCover->pIdx.
|
||||
*/
|
||||
static int exprIdxCover(Walker *pWalker, Expr *pExpr){
|
||||
if( pExpr->op==TK_COLUMN
|
||||
&& pExpr->iTable==pWalker->u.pIdxCover->iCur
|
||||
&& sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
|
||||
){
|
||||
pWalker->eCode = 1;
|
||||
return WRC_Abort;
|
||||
}
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** Determine if an index on table iCur that contains the columns in
|
||||
** Bitmask m will cover the expression pExpr. Return true if the index
|
||||
** does cover the expression and false if the expression references
|
||||
** table columns that are not found in the index.
|
||||
**
|
||||
** An index covering an expression means that the expression can be
|
||||
** evaluated using only the index and without having to lookup the
|
||||
** corresponding table entry.
|
||||
*/
|
||||
int sqlite3ExprCoveredByIndex(
|
||||
Expr *pExpr, /* The index to be tested */
|
||||
int iCur, /* The cursor number for the corresponding table */
|
||||
Index *pIdx /* The index that might be used for coverage */
|
||||
){
|
||||
Walker w;
|
||||
struct IdxCover xcov;
|
||||
memset(&w, 0, sizeof(w));
|
||||
xcov.iCur = iCur;
|
||||
xcov.pIdx = pIdx;
|
||||
w.xExprCallback = exprIdxCover;
|
||||
w.u.pIdxCover = &xcov;
|
||||
sqlite3WalkExpr(&w, pExpr);
|
||||
return !w.eCode;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** An instance of the following structure is used by the tree walker
|
||||
** to count references to table columns in the arguments of an
|
||||
|
@ -3257,6 +3257,7 @@ struct Walker {
|
||||
struct SrcCount *pSrcCount; /* Counting column references */
|
||||
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
|
||||
int *aiCol; /* array of column indexes */
|
||||
struct IdxCover *pIdxCover; /* Check for index coverage */
|
||||
} u;
|
||||
};
|
||||
|
||||
@ -3700,6 +3701,7 @@ int sqlite3ExprListCompare(ExprList*, ExprList*, int);
|
||||
int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
|
||||
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
|
||||
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
|
||||
int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
|
||||
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
|
||||
Vdbe *sqlite3GetVdbe(Parse*);
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
|
29
src/where.c
29
src/where.c
@ -2775,11 +2775,34 @@ static int whereLoopAddBtree(
|
||||
|
||||
/* The cost of visiting the index rows is N*K, where K is
|
||||
** between 1.1 and 3.0, depending on the relative sizes of the
|
||||
** index and table rows. If this is a non-covering index scan,
|
||||
** also add the cost of visiting table rows (N*3.0). */
|
||||
** index and table rows. */
|
||||
pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
|
||||
if( m!=0 ){
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
|
||||
/* If this is a non-covering index scan, add in the cost of
|
||||
** doing table lookups. The cost will be 3x the number of
|
||||
** lookups. Take into account WHERE clause terms that can be
|
||||
** satisfied using just the index, and that do not require a
|
||||
** table lookup. */
|
||||
LogEst nLookup = rSize + 16; /* Base cost: N*3 */
|
||||
int ii;
|
||||
int iCur = pSrc->iCursor;
|
||||
WhereClause *pWC = &pWInfo->sWC;
|
||||
for(ii=0; ii<pWC->nTerm; ii++){
|
||||
WhereTerm *pTerm = &pWC->a[ii];
|
||||
if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
|
||||
break;
|
||||
}
|
||||
/* pTerm can be evaluated using just the index. So reduce
|
||||
** the expected number of table lookups accordingly */
|
||||
if( pTerm->truthProb<=0 ){
|
||||
nLookup += pTerm->truthProb;
|
||||
}else{
|
||||
nLookup--;
|
||||
if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19;
|
||||
}
|
||||
}
|
||||
|
||||
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
|
||||
}
|
||||
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
|
||||
whereLoopOutputAdjust(pWC, pNew, rSize);
|
||||
|
Loading…
x
Reference in New Issue
Block a user