diff options
author | drh <drh@noemail.net> | 2013-10-10 20:13:18 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2013-10-10 20:13:18 +0000 |
commit | a63b85299290b7eca076ea6e031e7f43d4feadcf (patch) | |
tree | e925eb05965ec76f37b6483581d5bd8f8ea9e53b /src/analyze.c | |
parent | 59255f9a98381960cfede9253277f128895531f6 (diff) | |
parent | 7e65c94bdc689bebd222321dec5c034194267ac9 (diff) | |
download | sqlite-a63b85299290b7eca076ea6e031e7f43d4feadcf.tar.gz sqlite-a63b85299290b7eca076ea6e031e7f43d4feadcf.zip |
Synchronize with the trunk.
FossilOrigin-Name: 136445ba020c9475d3f5a7843d7d0add98477138
Diffstat (limited to 'src/analyze.c')
-rw-r--r-- | src/analyze.c | 149 |
1 files changed, 90 insertions, 59 deletions
diff --git a/src/analyze.c b/src/analyze.c index 89dc84f2c..c83133a4d 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -347,7 +347,7 @@ static void statInit( p->mxSample = mxSample; p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1); p->current.anLt = &p->current.anEq[nColUp]; - sqlite3_randomness(sizeof(p->iPrn), &p->iPrn); + p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[1])*0xd0944565; /* Set up the Stat4Accum.a[] and aBest[] arrays */ p->a = (struct Stat4Sample*)&p->current.anLt[nColUp]; @@ -371,8 +371,7 @@ static void statInit( } static const FuncDef statInitFuncdef = { 1+IsStat34, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ + SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statInit, /* xFunc */ @@ -383,24 +382,63 @@ static const FuncDef statInitFuncdef = { 0 /* pDestructor */ }; +#ifdef SQLITE_ENABLE_STAT4 +/* +** pNew and pOld are both candidate non-periodic samples selected for +** the same column (pNew->iCol==pOld->iCol). Ignoring this column and +** considering only any trailing columns and the sample hash value, this +** function returns true if sample pNew is to be preferred over pOld. +** In other words, if we assume that the cardinalities of the selected +** column for pNew and pOld are equal, is pNew to be preferred over pOld. +** +** This function assumes that for each argument sample, the contents of +** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid. +*/ +static int sampleIsBetterPost( + Stat4Accum *pAccum, + Stat4Sample *pNew, + Stat4Sample *pOld +){ + int nCol = pAccum->nCol; + int i; + assert( pNew->iCol==pOld->iCol ); + for(i=pNew->iCol+1; i<nCol; i++){ + if( pNew->anEq[i]>pOld->anEq[i] ) return 1; + if( pNew->anEq[i]<pOld->anEq[i] ) return 0; + } + if( pNew->iHash>pOld->iHash ) return 1; + return 0; +} +#endif + #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 /* ** Return true if pNew is to be preferred over pOld. +** +** This function assumes that for each argument sample, the contents of +** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid. */ -static int sampleIsBetter(Stat4Sample *pNew, Stat4Sample *pOld){ +static int sampleIsBetter( + Stat4Accum *pAccum, + Stat4Sample *pNew, + Stat4Sample *pOld +){ tRowcnt nEqNew = pNew->anEq[pNew->iCol]; tRowcnt nEqOld = pOld->anEq[pOld->iCol]; assert( pOld->isPSample==0 && pNew->isPSample==0 ); assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) ); - if( (nEqNew>nEqOld) - || (nEqNew==nEqOld && pNew->iCol<pOld->iCol) - || (nEqNew==nEqOld && pNew->iCol==pOld->iCol && pNew->iHash>pOld->iHash) - ){ - return 1; + if( (nEqNew>nEqOld) ) return 1; +#ifdef SQLITE_ENABLE_STAT4 + if( nEqNew==nEqOld ){ + if( pNew->iCol<pOld->iCol ) return 1; + return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld)); } return 0; +#else + return (nEqNew==nEqOld && pNew->iHash>pOld->iHash); +#endif } /* @@ -423,11 +461,10 @@ void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ Stat4Sample *pSample; int i; - i64 iSeq; - int iPos; assert( IsStat4 || nEqZero==0 ); +#ifdef SQLITE_ENABLE_STAT4 if( pNew->isPSample==0 ){ Stat4Sample *pUpgrade = 0; assert( pNew->anEq[pNew->iCol]>0 ); @@ -441,8 +478,9 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ Stat4Sample *pOld = &p->a[i]; if( pOld->anEq[pNew->iCol]==0 ){ if( pOld->isPSample ) return; - assert( sampleIsBetter(pNew, pOld) ); - if( pUpgrade==0 || sampleIsBetter(pOld, pUpgrade) ){ + assert( pOld->iCol>pNew->iCol ); + assert( sampleIsBetter(p, pNew, pOld) ); + if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){ pUpgrade = pOld; } } @@ -453,6 +491,7 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ goto find_new_min; } } +#endif /* If necessary, remove sample iMin to make room for the new sample. */ if( p->nSample>=p->mxSample ){ @@ -481,34 +520,17 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){ sampleCopy(p, pSample, pNew); p->nSample++; -#if 0 - iSeq = pNew->anLt[p->nCol-1]; - for(iPos=p->nSample; iPos>0; iPos--){ - if( iSeq>p->a[iPos-1].anLt[p->nCol-1] ) break; - } - - if( iPos!=p->nSample ){ - Stat4Sample *pEnd = &p->a[p->nSample]; - tRowcnt *anEq = pEnd->anEq; - tRowcnt *anLt = pEnd->anLt; - tRowcnt *anDLt = pEnd->anDLt; - memmove(&p->a[iPos], &p->a[iPos+1], (p->nSample-iPos)*sizeof(p->a[0])); - pSample->anEq = anEq; - pSample->anDLt = anDLt; - pSample->anLt = anLt; - } -#endif - - /* Zero the first nEqZero entries in the anEq[] array. */ memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero); +#ifdef SQLITE_ENABLE_STAT4 find_new_min: +#endif if( p->nSample>=p->mxSample ){ int iMin = -1; for(i=0; i<p->mxSample; i++){ if( p->a[i].isPSample ) continue; - if( iMin<0 || sampleIsBetter(&p->a[iMin], &p->a[i]) ){ + if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){ iMin = i; } } @@ -532,9 +554,8 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){ ** into IndexSample.a[] at this point. */ for(i=(p->nCol-2); i>=iChng; i--){ Stat4Sample *pBest = &p->aBest[i]; - if( p->nSample<p->mxSample - || sampleIsBetter(pBest, &p->a[p->iMin]) - ){ + pBest->anEq[i] = p->current.anEq[i]; + if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){ sampleInsert(p, pBest, i); } } @@ -561,7 +582,9 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){ }else /* Or if it is a non-periodic sample. Add it in this case too. */ - if( p->nSample<p->mxSample || sampleIsBetter(&p->current, &p->a[p->iMin]) ){ + if( p->nSample<p->mxSample + || sampleIsBetter(p, &p->current, &p->a[p->iMin]) + ){ sampleInsert(p, &p->current, 0); } } @@ -635,7 +658,7 @@ static void statPush( /* Update the aBest[] array. */ for(i=0; i<(p->nCol-1); i++){ p->current.iCol = i; - if( i>=iChng || sampleIsBetter(&p->current, &p->aBest[i]) ){ + if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){ sampleCopy(p, &p->aBest[i], &p->current); } } @@ -644,8 +667,7 @@ static void statPush( } static const FuncDef statPushFuncdef = { 2+IsStat34, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ + SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statPush, /* xFunc */ @@ -721,12 +743,12 @@ static void statGet( return; } - sqlite3_snprintf(24, zRet, "%lld", p->nRow); + sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow); z = zRet + sqlite3Strlen30(zRet); for(i=0; i<(p->nCol-1); i++){ - i64 nDistinct = p->current.anDLt[i] + 1; - i64 iVal = (p->nRow + nDistinct - 1) / nDistinct; - sqlite3_snprintf(24, z, " %lld", iVal); + u64 nDistinct = p->current.anDLt[i] + 1; + u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; + sqlite3_snprintf(24, z, " %llu", iVal); z += sqlite3Strlen30(z); assert( p->current.anEq[i] ); } @@ -767,7 +789,7 @@ static void statGet( int i; char *z = zRet; for(i=0; i<p->nCol; i++){ - sqlite3_snprintf(24, z, "%lld ", aCnt[i]); + sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]); z += sqlite3Strlen30(z); } assert( z[0]=='\0' && z>zRet ); @@ -780,8 +802,7 @@ static void statGet( } static const FuncDef statGetFuncdef = { 1+IsStat34, /* nArg */ - SQLITE_UTF8, /* iPrefEnc */ - 0, /* flags */ + SQLITE_UTF8, /* funcFlags */ 0, /* pUserData */ 0, /* pNext */ statGet, /* xFunc */ @@ -1229,18 +1250,16 @@ struct analysisInfo { ** the array aOut[]. */ static void decodeIntArray( - char *zIntArray, - int nOut, - tRowcnt *aOut, - int *pbUnordered + char *zIntArray, /* String containing int array to decode */ + int nOut, /* Number of slots in aOut[] */ + tRowcnt *aOut, /* Store integers here */ + Index *pIndex /* Handle extra flags for this index, if not NULL */ ){ char *z = zIntArray; int c; int i; tRowcnt v; - assert( pbUnordered==0 || *pbUnordered==0 ); - #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( z==0 ) z = ""; #else @@ -1255,8 +1274,19 @@ static void decodeIntArray( aOut[i] = v; if( *z==' ' ) z++; } - if( pbUnordered && strcmp(z, "unordered")==0 ){ - *pbUnordered = 1; +#ifndef SQLITE_ENABLE_STAT3_OR_STAT4 + assert( pIndex!=0 ); +#else + if( pIndex ) +#endif + { + if( strcmp(z, "unordered")==0 ){ + pIndex->bUnordered = 1; + }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ + int v32 = 0; + sqlite3GetInt32(z+3, &v32); + pIndex->szIdxRow = sqlite3LogEst(v32); + } } } @@ -1295,12 +1325,13 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ z = argv[2]; if( pIndex ){ - int bUnordered = 0; - decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst,&bUnordered); + decodeIntArray((char*)z, pIndex->nColumn+1, pIndex->aiRowEst, pIndex); if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0]; - pIndex->bUnordered = bUnordered; }else{ - decodeIntArray((char*)z, 1, &pTable->nRowEst, 0); + Index fakeIdx; + fakeIdx.szIdxRow = pTable->szTabRow; + decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx); + pTable->szTabRow = fakeIdx.szIdxRow; } return 0; |