From: drh Date: Fri, 31 May 2013 12:43:55 +0000 (+0000) Subject: Improved detection of unnecessary ORDER BY clauses. X-Git-Tag: version-3.8.0~130^2~60 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d044d209f3535e4a514dd9bbad7000e4432e685e;p=thirdparty%2Fsqlite.git Improved detection of unnecessary ORDER BY clauses. FossilOrigin-Name: 58805eb36b9975706e2c4e382689519454e9a504 --- diff --git a/manifest b/manifest index dbb58ea9b3..edf228f872 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sconstructAutomaticIndex()\sroutine\sso\sthat\sit\sworks\swith\sNGQP. -D 2013-05-31T11:57:39.405 +C Improved\sdetection\sof\sunnecessary\sORDER\sBY\sclauses. +D 2013-05-31T12:43:55.143 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -289,7 +289,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83 F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73 -F src/where.c 530dd22d4f803747e964edcb052d699c4c92e1a1 +F src/where.c 0e1c41804f89dbfd48fbe8dfa68adc6b6d682a75 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1093,7 +1093,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 24a2e9ddcecd3926817d77abbb75d068ee7140ad -R 92deaa75392a3f586cae6bde8f65a470 +P 5e1e61399513b4a95fd93df2377a2603f1670063 +R 17288f799b200fcc6199a08359305634 U drh -Z 293d3cdab228aa747c73a2994c326e63 +Z 9542ccfa5fa5ec11248b1f41f8b389ee diff --git a/manifest.uuid b/manifest.uuid index 57b2c0e51a..ec86401b40 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5e1e61399513b4a95fd93df2377a2603f1670063 \ No newline at end of file +58805eb36b9975706e2c4e382689519454e9a504 \ No newline at end of file diff --git a/src/where.c b/src/where.c index dea0ff2fdd..249cc724b1 100644 --- a/src/where.c +++ b/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 ** and no insert will occur if an existing WhereLoop is faster and has ** 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 ** 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. ** (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 +** (5) The template uses more terms of the same index but has no additional +** dependencies */ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ 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 */ WhereLoop *pNew; /* Template WhereLoop object */ int rc = SQLITE_OK; /* Return code */ - int iSortIdx = 0; /* Index number */ + int iSortIdx = 1; /* Index number */ int b; /* A boolean value */ double rSize; /* 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; /* Full table scan */ + pNew->iSortIdx = b ? iSortIdx : 0; pNew->nOut = rSize; pNew->rRun = (rSize + rLogSize)*(3+b); /* 4x penalty for a full-scan */ rc = whereLoopInsert(pBuilder, pNew); @@ -4513,8 +4516,9 @@ static int wherePathSatisfiesOrderBy( u8 revSet; /* True if rev is known */ u8 rev; /* Composite sort order */ u8 revIdx; /* Index sort order */ - u8 isUnique; - u8 requireUnique = 0; + u8 isOneRow; /* Current WhereLoop is a one-row loop */ + u8 requireOneRow = 0; /* All subsequent loops must be one-row */ + u8 isUniqueIdx; /* Current WhereLoop uses a unique index */ u16 nColumn; u16 nOrderBy; int i, j; @@ -4547,6 +4551,10 @@ static int wherePathSatisfiesOrderBy( ** of the index. ** ** (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 ); @@ -4569,10 +4577,10 @@ static int wherePathSatisfiesOrderBy( for(i=0; i<=nLoop && nUsedaLoop[i] : pLast; assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); - isUnique = 1; + isOneRow = isUniqueIdx = 1; if( pLoop->wsFlags & WHERE_IPK ){ - if( (pLoop->wsFlags & WHERE_COLUMN_IN)!=0 ) isUnique = 0; - if( pLoop->u.btree.nEq!=1 ) isUnique = 0; + if( (pLoop->wsFlags & WHERE_COLUMN_IN)!=0 ) isOneRow = 0; + if( pLoop->u.btree.nEq!=1 ) isOneRow = 0; pIndex = 0; nColumn = 0; }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){ @@ -4580,16 +4588,16 @@ static int wherePathSatisfiesOrderBy( }else{ nColumn = pIndex->nColumn; if( pIndex->onError==OE_None ){ - isUnique = 0; + isOneRow = isUniqueIdx = 0; }else if( (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_RANGE |WHERE_COLUMN_NULL))!=0 ){ - isUnique = 0; + isOneRow = 0; }else if( pLoop->u.btree.nEq < pIndex->nColumn ){ - isUnique = 0; + isOneRow = 0; } } - if( !isUnique && requireUnique ) return 0; - requireUnique = !isUnique; + if( !isOneRow && requireOneRow ) return 0; + requireOneRow = !isOneRow; iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; j = 0; revSet = rev = 0; @@ -4598,7 +4606,7 @@ static int wherePathSatisfiesOrderBy( pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[nUsed].pExpr); assert( pOBExpr->op==TK_COLUMN ); if( pOBExpr->iTable!=iCur ) break; - if( isUnique ) continue; + if( isOneRow ){ j--; continue; } if( jaiColumn[j]; @@ -4629,6 +4637,7 @@ static int wherePathSatisfiesOrderBy( revSet = 1; } } + if( j>=nColumn-1 && isUniqueIdx ){ j--; isOneRow = 1; } } if( rev ) revMask |= ((Bitmask)1)<