From a161c222a6cca5ab4cf03befaa28853a7f204119 Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 7 Oct 2013 16:53:50 +0000 Subject: [PATCH] Try to remember statistics from ANALYZE using LogEst instead of u64. FossilOrigin-Name: 8e78557a40a6b97009852f5b72e68d6483fb00fc --- manifest | 25 ++++++++------- manifest.uuid | 2 +- src/analyze.c | 30 +++++++++--------- src/build.c | 21 +++++++------ src/select.c | 4 +-- src/sqliteInt.h | 12 ++++---- src/util.c | 1 - src/where.c | 82 ++++++++++++++++++++++++------------------------- 8 files changed, 90 insertions(+), 87 deletions(-) diff --git a/manifest b/manifest index 824d937e64..a344626fc7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sbug\sfixes\sfrom\strunk. -D 2013-10-07T10:48:06.076 +C Try\sto\sremember\sstatistics\sfrom\sANALYZE\susing\sLogEst\sinstead\sof\su64. +D 2013-10-07T16:53:50.515 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -157,7 +157,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083 -F src/analyze.c c27da55795a11d09bea74259782c3e11e9750534 +F src/analyze.c 3994309c21b7324217cd32225b7abb5cb1bd1946 F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34 F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3 @@ -166,7 +166,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c d5720cbb21ae56e7e5b07847e05e5b203818acac F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0 -F src/build.c ea07ec35354cdcd017b128679391320220030336 +F src/build.c 46bb89df0a204eb7154874f966f11d16a7fbced7 F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c @@ -216,12 +216,12 @@ F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68 F src/resolve.c 7459801d02997b07e8b8da85ef255392ba1d022b F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 13be733297f415b388444a2e296d23569cd83b8a +F src/select.c 19611e6da6646a1090164b29d6b23b7c8e7364ea F src/shell.c 5ee50ca3e35453bbd6ccdf1bdd0f6bbe9738e9fb F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h 5dbfc960fb39dbb55ba16697f453b03cd759b04a +F src/sqliteInt.h a5fa87b540662fb552ba81c0d4eeb368aebb5af7 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -275,7 +275,7 @@ F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2 F src/trigger.c ba0a883cd536b7dfdd4df3733001f5372a4299da F src/update.c f5182157f5d0d0a97bc5f5e3c9bdba0dfbe08f08 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 -F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918 +F src/util.c 2f0c9b1f884d038eb90f48cf17042a88dc1629d3 F src/vacuum.c f313bc97123a4dd4bfd3f50a00c4d44c08a5b1b7 F src/vdbe.c 56e648f5ba9a91810caf216857adfed9039cd174 F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4 @@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74 -F src/where.c 72c6c205e53ae72d2d235705bb2b040d70fff2e2 +F src/where.c 7916e32a4d7f8cc891a08de09380ef519415d275 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1121,7 +1121,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P e9e932aa400f217e383cda9922fbde8a4356f57a 0aca31e1514b3df254c049b4251bcb199831681a -R 58571132dec54639078eadde66ba0889 +P 1d7b2dc0eae70c0c0e523b715acf758bb4cfa9ac +R faf619696f929769ec0cefbeba9e27c2 +T *branch * log-stats +T *sym-log-stats * +T -sym-row-size-est * U drh -Z 412c711013eb3a5449cb7f9aec9f3c69 +Z 72baf94bdfc7ce8839761e1732e0e2d4 diff --git a/manifest.uuid b/manifest.uuid index eb89607625..8c783a8a31 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1d7b2dc0eae70c0c0e523b715acf758bb4cfa9ac \ No newline at end of file +8e78557a40a6b97009852f5b72e68d6483fb00fc \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 84232ebe5d..8b0d9797e3 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1252,13 +1252,13 @@ struct analysisInfo { static void decodeIntArray( char *zIntArray, /* String containing int array to decode */ int nOut, /* Number of slots in aOut[] */ - tRowcnt *aOut, /* Store integers here */ + LogEst *aOut, /* Convert values to 10*log2() and store here */ Index *pIndex /* Handle extra flags for this index, if not NULL */ ){ char *z = zIntArray; int c; int i; - tRowcnt v; + u64 v; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( z==0 ) z = ""; @@ -1271,7 +1271,7 @@ static void decodeIntArray( v = v*10 + c - '0'; z++; } - aOut[i] = v; + aOut[i] = sqlite3LogEst(v); if( *z==' ' ) z++; } if( pIndex ){ @@ -1368,10 +1368,10 @@ static void initAvgEq(Index *pIdx){ int iCol; for(iCol=0; iColnColumn; iCol++){ int i; /* Used to iterate through samples */ - tRowcnt sumEq = 0; /* Sum of the nEq values */ - tRowcnt nSum = 0; /* Number of terms contributing to sumEq */ - tRowcnt avgEq = 0; - tRowcnt nDLt = pFinal->anDLt[iCol]; + u64 sumEq = 0; /* Sum of the nEq values */ + u64 nSum = 0; /* Number of terms contributing to sumEq */ + u64 avgEq = 0; + u64 nDLt = sqlite3LogEstToInt(pFinal->anDLt[iCol]); /* Set nSum to the number of distinct (iCol+1) field prefixes that ** occur in the stat4 table for this index before pFinal. Set @@ -1380,15 +1380,15 @@ static void initAvgEq(Index *pIdx){ ** prefixes). */ for(i=0; i<(pIdx->nSample-1); i++){ if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){ - sumEq += aSample[i].anEq[iCol]; + sumEq += sqlite3LogEstToInt(aSample[i].anEq[iCol]); nSum++; } } if( nDLt>nSum ){ - avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum); + avgEq = (sqlite3LogEstToInt(pFinal->anLt[iCol]) - sumEq)/(nDLt - nSum); } - if( avgEq==0 ) avgEq = 1; - pIdx->aAvgEq[iCol] = avgEq; + if( avgEq<=0 ) avgEq = 1; + pIdx->aAvgEq[iCol] = sqlite3LogEst(avgEq); if( pIdx->nSampleCol==1 ) break; } } @@ -1438,7 +1438,7 @@ static int loadStatTbl( int nSample; /* Number of samples */ int nByte; /* Bytes of space required */ int i; /* Bytes of space required */ - tRowcnt *pSpace; + LogEst *pSpace; zIndex = (char *)sqlite3_column_text(pStmt, 0); if( zIndex==0 ) continue; @@ -1454,15 +1454,15 @@ static int loadStatTbl( } pIdx->nSampleCol = nIdxCol; nByte = sizeof(IndexSample) * nSample; - nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; - nByte += nAvgCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ + nByte += sizeof(LogEst) * nIdxCol * 3 * nSample; + nByte += nAvgCol * sizeof(LogEst); /* Space for Index.aAvgEq[] */ pIdx->aSample = sqlite3DbMallocZero(db, nByte); if( pIdx->aSample==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM; } - pSpace = (tRowcnt*)&pIdx->aSample[nSample]; + pSpace = (LogEst*)&pIdx->aSample[nSample]; pIdx->aAvgEq = pSpace; pSpace += nAvgCol; for(i=0; iaSample[i].anEq = pSpace; pSpace += nIdxCol; diff --git a/src/build.c b/src/build.c index 3c8d22d3cd..e5e4eeb908 100644 --- a/src/build.c +++ b/src/build.c @@ -879,7 +879,7 @@ void sqlite3StartTable( pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; - pTable->nRowEst = 1000000; + pTable->nRowEst = 200; assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; @@ -2722,7 +2722,7 @@ Index *sqlite3CreateIndex( nCol = pList->nExpr; pIndex = sqlite3DbMallocZero(db, ROUND8(sizeof(Index)) + /* Index structure */ - ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */ + ROUND8(sizeof(LogEst)*(nCol+1)) + /* Index.aiRowEst */ sizeof(char *)*nCol + /* Index.azColl */ sizeof(int)*nCol + /* Index.aiColumn */ sizeof(u8)*nCol + /* Index.aSortOrder */ @@ -2733,9 +2733,9 @@ Index *sqlite3CreateIndex( goto exit_create_index; } zExtra = (char*)pIndex; - pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))]; + pIndex->aiRowEst = (LogEst*)&zExtra[ROUND8(sizeof(Index))]; pIndex->azColl = (char**) - ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1)); + ((char*)pIndex->aiRowEst + ROUND8(sizeof(LogEst)*nCol+1)); assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) ); assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) ); pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); @@ -3014,19 +3014,20 @@ exit_create_index: ** are based on typical values found in actual indices. */ void sqlite3DefaultRowEst(Index *pIdx){ - tRowcnt *a = pIdx->aiRowEst; + LogEst *a = pIdx->aiRowEst; int i; - tRowcnt n; + LogEst n; assert( a!=0 ); a[0] = pIdx->pTable->nRowEst; - if( a[0]<10 ) a[0] = 10; - n = 10; + assert( 33==sqlite3LogEst(10) ); + if( a[0]<34 ){ a[0] = 34; } + n = 34; for(i=1; i<=pIdx->nColumn; i++){ a[i] = n; - if( n>5 ) n--; + if( n>24 ) n -= 2; } if( pIdx->onError!=OE_None ){ - a[pIdx->nColumn] = 1; + a[pIdx->nColumn] = 0; } } diff --git a/src/select.c b/src/select.c index f9c7835fd2..eee681ff20 100644 --- a/src/select.c +++ b/src/select.c @@ -1480,7 +1480,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ assert( db->lookaside.bEnabled==0 ); pTab->nRef = 1; pTab->zName = 0; - pTab->nRowEst = 1000000; + pTab->nRowEst = 200; selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect); pTab->iPKey = -1; @@ -3398,7 +3398,7 @@ static int selectExpander(Walker *pWalker, Select *p){ while( pSel->pPrior ){ pSel = pSel->pPrior; } selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); pTab->iPKey = -1; - pTab->nRowEst = 1000000; + pTab->nRowEst = 200; pTab->tabFlags |= TF_Ephemeral; #endif }else{ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b02fb12b26..fe8e3f919a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1382,11 +1382,11 @@ struct Table { #ifndef SQLITE_OMIT_CHECK ExprList *pCheck; /* All CHECK constraints */ #endif - tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ int tnum; /* Root BTree node for this table (see note above) */ i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ + LogEst nRowEst; /* Estimated number of rows in the table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ @@ -1577,7 +1577,7 @@ struct UnpackedRecord { struct Index { char *zName; /* Name of this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ - tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ + LogEst *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ Table *pTable; /* The SQL table being indexed */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ @@ -1595,7 +1595,7 @@ struct Index { #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ - tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ + LogEst *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; @@ -1608,9 +1608,9 @@ struct Index { struct IndexSample { void *p; /* Pointer to sampled record */ int n; /* Size of record in bytes */ - tRowcnt *anEq; /* Est. number of rows where the key equals this sample */ - tRowcnt *anLt; /* Est. number of rows where key is less than this sample */ - tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */ + LogEst *anEq; /* Est. number of rows where the key equals this sample */ + LogEst *anLt; /* Est. number of rows where key is less than this sample */ + LogEst *anDLt; /* Est. number of distinct keys less than this sample */ }; /* diff --git a/src/util.c b/src/util.c index 50ffd98650..72e6e17e75 100644 --- a/src/util.c +++ b/src/util.c @@ -1213,7 +1213,6 @@ void sqlite3FileSuffix3(const char *zBaseFilename, char *z){ ** Find (an approximate) sum of two LogEst values. This computation is ** not a simple "+" operator because LogEst is stored as a logarithmic ** value. -** */ LogEst sqlite3LogEstAdd(LogEst a, LogEst b){ static const unsigned char x[] = { diff --git a/src/where.c b/src/where.c index 98af69b10c..0f160b80b7 100644 --- a/src/where.c +++ b/src/where.c @@ -2328,7 +2328,7 @@ static void whereKeyStats( Index *pIdx, /* Index to consider domain of */ UnpackedRecord *pRec, /* Vector of values to consider */ int roundUp, /* Round up if true. Round down if false */ - tRowcnt *aStat /* OUT: stats written here */ + LogEst *aStat /* OUT: stats written here */ ){ IndexSample *aSample = pIdx->aSample; int iCol; /* Index of required stats in anEq[] etc. */ @@ -2381,15 +2381,16 @@ static void whereKeyStats( aStat[0] = aSample[i].anLt[iCol]; aStat[1] = aSample[i].anEq[iCol]; }else{ - tRowcnt iLower, iUpper, iGap; + LogEst iLower, iUpper, iGap; if( i==0 ){ iLower = 0; iUpper = aSample[0].anLt[iCol]; }else{ iUpper = i>=pIdx->nSample ? pIdx->aiRowEst[0] : aSample[i].anLt[iCol]; - iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol]; + iLower = sqlite3LogEstAdd(aSample[i-1].anEq[iCol], + aSample[i-1].anLt[iCol]); } - aStat[1] = (pIdx->nColumn>iCol ? pIdx->aAvgEq[iCol] : 1); + aStat[1] = (pIdx->nColumn>iCol ? pIdx->aAvgEq[iCol] : 0); if( iLower>=iUpper ){ iGap = 0; }else{ @@ -2466,7 +2467,7 @@ static int whereRangeScanEst( && OptimizationEnabled(pParse->db, SQLITE_Stat3) ){ UnpackedRecord *pRec = pBuilder->pRec; - tRowcnt a[2]; + LogEst a[2]; u8 aff; /* Variable iLower will be set to the estimate of the number of rows in @@ -2486,8 +2487,8 @@ static int whereRangeScanEst( ** is either ($P) or ($P:$U). Again, even if $U is available, both values ** of iUpper are requested of whereKeyStats() and the smaller used. */ - tRowcnt iLower; - tRowcnt iUpper; + LogEst iLower; + LogEst iUpper; if( nEq==p->nColumn ){ aff = SQLITE_AFF_INTEGER; @@ -2503,7 +2504,7 @@ static int whereRangeScanEst( ** have been requested when testing key $P in whereEqualScanEst(). */ whereKeyStats(pParse, p, pRec, 0, a); iLower = a[0]; - iUpper = a[0] + a[1]; + iUpper = sqlite3LogEstAdd(a[0],a[1]); } /* If possible, improve on the iLower estimate using ($P:$L). */ @@ -2513,9 +2514,9 @@ static int whereRangeScanEst( assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 ); rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ - tRowcnt iNew; + LogEst iNew; whereKeyStats(pParse, p, pRec, 0, a); - iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0); + iNew = sqlite3LogEstAdd(a[0],((pLower->eOperator & WO_GT) ? a[1] : 0)); if( iNew>iLower ) iLower = iNew; nOut--; } @@ -2528,9 +2529,9 @@ static int whereRangeScanEst( assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ - tRowcnt iNew; + LogEst iNew; whereKeyStats(pParse, p, pRec, 1, a); - iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0); + iNew = sqlite3LogEstAdd(a[0],((pUpper->eOperator & WO_LE) ? a[1] : 0)); if( iNewpRec = pRec; if( rc==SQLITE_OK ){ - if( iUpper>iLower ){ - nNew = sqlite3LogEst(iUpper - iLower); - }else{ - nNew = 10; assert( 10==sqlite3LogEst(2) ); - } + if( iUpper<=iLower ) iUpper = iLower+1; + nNew = sqlite3LogEst(sqlite3LogEstToInt(iUpper) + - sqlite3LogEstToInt(iLower)); if( nNewpNew->u.btree.pIndex; int nEq = pBuilder->pNew->u.btree.nEq; UnpackedRecord *pRec = pBuilder->pRec; u8 aff; /* Column affinity */ int rc; /* Subfunction return code */ - tRowcnt a[2]; /* Statistics */ + LogEst a[2]; /* Statistics */ int bOk; assert( nEq>=1 ); @@ -2633,7 +2634,8 @@ static int whereEqualScanEst( pBuilder->nRecValid = nEq; whereKeyStats(pParse, p, pRec, 0, a); - WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1])); + WHERETRACE(0x100,("equality scan regions: %d (%llu)\n", a[1], + sqlite3LogEstToInt(a[1]))); *pnRow = a[1]; return rc; @@ -2661,27 +2663,28 @@ static int whereInScanEst( Parse *pParse, /* Parsing & code generating context */ WhereLoopBuilder *pBuilder, ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ - tRowcnt *pnRow /* Write the revised row estimate here */ + LogEst *pnRow /* Write the revised row estimate here */ ){ Index *p = pBuilder->pNew->u.btree.pIndex; int nRecValid = pBuilder->nRecValid; int rc = SQLITE_OK; /* Subfunction return code */ - tRowcnt nEst; /* Number of rows for a single term */ - tRowcnt nRowEst = 0; /* New estimate of the number of rows */ + LogEst nEst; /* Number of rows for a single term */ + u64 nRowEst = 0; /* New estimate of the number of rows */ int i; /* Loop counter */ assert( p->aSample!=0 ); for(i=0; rc==SQLITE_OK && inExpr; i++){ nEst = p->aiRowEst[0]; rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); - nRowEst += nEst; + nRowEst += sqlite3LogEstToInt(nEst); pBuilder->nRecValid = nRecValid; } if( rc==SQLITE_OK ){ - if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; - *pnRow = nRowEst; - WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst)); + nEst = sqlite3LogEst(nRowEst); + if( nEst > p->aiRowEst[0] ) nEst = p->aiRowEst[0]; + *pnRow = nEst; + WHERETRACE(0x100,("IN row estimate: est=%d (%llu)\n", nEst, nRowEst)); } assert( pBuilder->nRecValid==nRecValid ); return rc; @@ -4251,8 +4254,8 @@ 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 = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]); - if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1; + nRowEst = pProbe->aiRowEst[pNew->u.btree.nEq+1]; + if( nRowEst<10 && pProbe->onError==OE_None ) nRowEst = 10; }else{ iCol = -1; nRowEst = 0; @@ -4265,7 +4268,7 @@ static int whereLoopAddBtreeIndex( saved_prereq = pNew->prereq; saved_nOut = pNew->nOut; pNew->rSetup = 0; - rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0])); + rLogSize = estLog(pProbe->aiRowEst[0]); for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ int nIn = 0; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 @@ -4346,7 +4349,7 @@ static int whereLoopAddBtreeIndex( && OptimizationEnabled(db, SQLITE_Stat3) ){ Expr *pExpr = pTerm->pExpr; - tRowcnt nOut = 0; + LogEst nOut = pNew->nOut; if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){ testcase( pTerm->eOperator & WO_EQ ); testcase( pTerm->eOperator & WO_ISNULL ); @@ -4355,11 +4358,8 @@ static int whereLoopAddBtreeIndex( && !ExprHasProperty(pExpr, EP_xIsSelect) ){ rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); } - assert( nOut==0 || rc==SQLITE_OK ); - if( nOut ){ - nOut = sqlite3LogEst(nOut); - pNew->nOut = MIN(nOut, saved_nOut); - } + assert( nOut==pNew->nOut || rc==SQLITE_OK ); + if( nOutnOut ) pNew->nOut = nOut; } #endif if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ @@ -4460,7 +4460,7 @@ static int whereLoopAddBtree( WhereInfo *pWInfo; /* WHERE analysis context */ Index *pProbe; /* An index we are evaluating */ Index sPk; /* A fake index object for the primary key */ - tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ + LogEst aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ SrcList *pTabList; /* The FROM clause */ struct SrcList_item *pSrc; /* The FROM clause btree term to add */ @@ -4495,7 +4495,7 @@ static int whereLoopAddBtree( sPk.onError = OE_Replace; sPk.pTable = pSrc->pTab; aiRowEstPk[0] = pSrc->pTab->nRowEst; - aiRowEstPk[1] = 1; + aiRowEstPk[1] = 0; pFirst = pSrc->pTab->pIndex; if( pSrc->notIndexed==0 ){ /* The real indices of the table are only considered if the @@ -4504,7 +4504,7 @@ static int whereLoopAddBtree( } pProbe = &sPk; } - rSize = sqlite3LogEst(pSrc->pTab->nRowEst); + rSize = pSrc->pTab->nRowEst; rLogSize = estLog(rSize); #ifndef SQLITE_OMIT_AUTOMATIC_INDEX -- 2.39.5