mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Improved detection of unnecessary ORDER BY clauses.
FossilOrigin-Name: 58805eb36b9975706e2c4e382689519454e9a504
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\sthe\sconstructAutomaticIndex()\sroutine\sso\sthat\sit\sworks\swith\sNGQP.
|
C Improved\sdetection\sof\sunnecessary\sORDER\sBY\sclauses.
|
||||||
D 2013-05-31T11:57:39.405
|
D 2013-05-31T12:43:55.143
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -289,7 +289,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
|
|||||||
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
|
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
||||||
F src/where.c 530dd22d4f803747e964edcb052d699c4c92e1a1
|
F src/where.c 0e1c41804f89dbfd48fbe8dfa68adc6b6d682a75
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||||
@@ -1093,7 +1093,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||||
P 24a2e9ddcecd3926817d77abbb75d068ee7140ad
|
P 5e1e61399513b4a95fd93df2377a2603f1670063
|
||||||
R 92deaa75392a3f586cae6bde8f65a470
|
R 17288f799b200fcc6199a08359305634
|
||||||
U drh
|
U drh
|
||||||
Z 293d3cdab228aa747c73a2994c326e63
|
Z 9542ccfa5fa5ec11248b1f41f8b389ee
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
5e1e61399513b4a95fd93df2377a2603f1670063
|
58805eb36b9975706e2c4e382689519454e9a504
|
||||||
35
src/where.c
35
src/where.c
@@ -3832,7 +3832,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
|||||||
** is better and has fewer dependencies. Or the template will be ignored
|
** is better and has fewer dependencies. Or the template will be ignored
|
||||||
** and no insert will occur if an existing WhereLoop is faster and has
|
** and no insert will occur if an existing WhereLoop is faster and has
|
||||||
** fewer dependencies than the template. Otherwise a new WhereLoop is
|
** fewer dependencies than the template. Otherwise a new WhereLoop is
|
||||||
** added based no the template.
|
** added based on the template.
|
||||||
**
|
**
|
||||||
** If pBuilder->pBest is not NULL then we only care about the very
|
** If pBuilder->pBest is not NULL then we only care about the very
|
||||||
** best template and that template should be stored in pBuilder->pBest.
|
** best template and that template should be stored in pBuilder->pBest.
|
||||||
@@ -3848,6 +3848,8 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
|
|||||||
** (2) They have the same iSortIdx.
|
** (2) They have the same iSortIdx.
|
||||||
** (3) The template has same or fewer dependencies than the current loop
|
** (3) The template has same or fewer dependencies than the current loop
|
||||||
** (4) The template has the same or lower cost than the current loop
|
** (4) The template has the same or lower cost than the current loop
|
||||||
|
** (5) The template uses more terms of the same index but has no additional
|
||||||
|
** dependencies
|
||||||
*/
|
*/
|
||||||
static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
||||||
WhereLoop **ppPrev, *p, *pNext = 0, *pToFree = 0;
|
WhereLoop **ppPrev, *p, *pNext = 0, *pToFree = 0;
|
||||||
@@ -4100,7 +4102,7 @@ static int whereLoopAddBtree(
|
|||||||
struct SrcList_item *pSrc; /* The FROM clause btree term to add */
|
struct SrcList_item *pSrc; /* The FROM clause btree term to add */
|
||||||
WhereLoop *pNew; /* Template WhereLoop object */
|
WhereLoop *pNew; /* Template WhereLoop object */
|
||||||
int rc = SQLITE_OK; /* Return code */
|
int rc = SQLITE_OK; /* Return code */
|
||||||
int iSortIdx = 0; /* Index number */
|
int iSortIdx = 1; /* Index number */
|
||||||
int b; /* A boolean value */
|
int b; /* A boolean value */
|
||||||
double rSize; /* number of rows in the table */
|
double rSize; /* number of rows in the table */
|
||||||
double rLogSize; /* Logarithm of the number of rows in the table */
|
double rLogSize; /* Logarithm of the number of rows in the table */
|
||||||
@@ -4179,6 +4181,7 @@ static int whereLoopAddBtree(
|
|||||||
pNew->wsFlags = WHERE_IPK;
|
pNew->wsFlags = WHERE_IPK;
|
||||||
|
|
||||||
/* Full table scan */
|
/* Full table scan */
|
||||||
|
pNew->iSortIdx = b ? iSortIdx : 0;
|
||||||
pNew->nOut = rSize;
|
pNew->nOut = rSize;
|
||||||
pNew->rRun = (rSize + rLogSize)*(3+b); /* 4x penalty for a full-scan */
|
pNew->rRun = (rSize + rLogSize)*(3+b); /* 4x penalty for a full-scan */
|
||||||
rc = whereLoopInsert(pBuilder, pNew);
|
rc = whereLoopInsert(pBuilder, pNew);
|
||||||
@@ -4513,8 +4516,9 @@ static int wherePathSatisfiesOrderBy(
|
|||||||
u8 revSet; /* True if rev is known */
|
u8 revSet; /* True if rev is known */
|
||||||
u8 rev; /* Composite sort order */
|
u8 rev; /* Composite sort order */
|
||||||
u8 revIdx; /* Index sort order */
|
u8 revIdx; /* Index sort order */
|
||||||
u8 isUnique;
|
u8 isOneRow; /* Current WhereLoop is a one-row loop */
|
||||||
u8 requireUnique = 0;
|
u8 requireOneRow = 0; /* All subsequent loops must be one-row */
|
||||||
|
u8 isUniqueIdx; /* Current WhereLoop uses a unique index */
|
||||||
u16 nColumn;
|
u16 nColumn;
|
||||||
u16 nOrderBy;
|
u16 nOrderBy;
|
||||||
int i, j;
|
int i, j;
|
||||||
@@ -4547,6 +4551,10 @@ static int wherePathSatisfiesOrderBy(
|
|||||||
** of the index.
|
** of the index.
|
||||||
**
|
**
|
||||||
** (4) Index columns past nEq must match ORDER BY terms one-for-one.
|
** (4) Index columns past nEq must match ORDER BY terms one-for-one.
|
||||||
|
**
|
||||||
|
** (5) If all columns of a UNIQUE index have been matched against ORDER BY
|
||||||
|
** terms, then any subsequent entries in the ORDER BY clause against the
|
||||||
|
** same table can be skipped.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
assert( pOrderBy!=0 );
|
assert( pOrderBy!=0 );
|
||||||
@@ -4569,10 +4577,10 @@ static int wherePathSatisfiesOrderBy(
|
|||||||
for(i=0; i<=nLoop && nUsed<nOrderBy; i++){
|
for(i=0; i<=nLoop && nUsed<nOrderBy; i++){
|
||||||
pLoop = i<nLoop ? pPath->aLoop[i] : pLast;
|
pLoop = i<nLoop ? pPath->aLoop[i] : pLast;
|
||||||
assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
|
assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
|
||||||
isUnique = 1;
|
isOneRow = isUniqueIdx = 1;
|
||||||
if( pLoop->wsFlags & WHERE_IPK ){
|
if( pLoop->wsFlags & WHERE_IPK ){
|
||||||
if( (pLoop->wsFlags & WHERE_COLUMN_IN)!=0 ) isUnique = 0;
|
if( (pLoop->wsFlags & WHERE_COLUMN_IN)!=0 ) isOneRow = 0;
|
||||||
if( pLoop->u.btree.nEq!=1 ) isUnique = 0;
|
if( pLoop->u.btree.nEq!=1 ) isOneRow = 0;
|
||||||
pIndex = 0;
|
pIndex = 0;
|
||||||
nColumn = 0;
|
nColumn = 0;
|
||||||
}else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
|
}else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
|
||||||
@@ -4580,16 +4588,16 @@ static int wherePathSatisfiesOrderBy(
|
|||||||
}else{
|
}else{
|
||||||
nColumn = pIndex->nColumn;
|
nColumn = pIndex->nColumn;
|
||||||
if( pIndex->onError==OE_None ){
|
if( pIndex->onError==OE_None ){
|
||||||
isUnique = 0;
|
isOneRow = isUniqueIdx = 0;
|
||||||
}else if( (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_RANGE
|
}else if( (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_RANGE
|
||||||
|WHERE_COLUMN_NULL))!=0 ){
|
|WHERE_COLUMN_NULL))!=0 ){
|
||||||
isUnique = 0;
|
isOneRow = 0;
|
||||||
}else if( pLoop->u.btree.nEq < pIndex->nColumn ){
|
}else if( pLoop->u.btree.nEq < pIndex->nColumn ){
|
||||||
isUnique = 0;
|
isOneRow = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( !isUnique && requireUnique ) return 0;
|
if( !isOneRow && requireOneRow ) return 0;
|
||||||
requireUnique = !isUnique;
|
requireOneRow = !isOneRow;
|
||||||
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
|
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
|
||||||
j = 0;
|
j = 0;
|
||||||
revSet = rev = 0;
|
revSet = rev = 0;
|
||||||
@@ -4598,7 +4606,7 @@ static int wherePathSatisfiesOrderBy(
|
|||||||
pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[nUsed].pExpr);
|
pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[nUsed].pExpr);
|
||||||
assert( pOBExpr->op==TK_COLUMN );
|
assert( pOBExpr->op==TK_COLUMN );
|
||||||
if( pOBExpr->iTable!=iCur ) break;
|
if( pOBExpr->iTable!=iCur ) break;
|
||||||
if( isUnique ) continue;
|
if( isOneRow ){ j--; continue; }
|
||||||
if( j<nColumn ){
|
if( j<nColumn ){
|
||||||
/* Normal index columns */
|
/* Normal index columns */
|
||||||
iColumn = pIndex->aiColumn[j];
|
iColumn = pIndex->aiColumn[j];
|
||||||
@@ -4629,6 +4637,7 @@ static int wherePathSatisfiesOrderBy(
|
|||||||
revSet = 1;
|
revSet = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( j>=nColumn-1 && isUniqueIdx ){ j--; isOneRow = 1; }
|
||||||
}
|
}
|
||||||
if( rev ) revMask |= ((Bitmask)1)<<i;
|
if( rev ) revMask |= ((Bitmask)1)<<i;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user