Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -2449,11 +2449,10 @@ || (pNew->wsFlags & WHERE_SKIPSCAN)!=0 ); if( eOp & WO_IN ){ Expr *pExpr = pTerm->pExpr; - LogEst M, logK; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ int i; nIn = 46; assert( 46==sqlite3LogEst(25) ); @@ -2470,10 +2469,11 @@ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); assert( nIn>0 ); /* RHS always has 2 or more terms... The parser ** changes "x IN (?)" into "x=?". */ } if( pProbe->hasStat1 ){ + LogEst M, logK, safetyMargin; /* Let: ** N = the total number of rows in the table ** K = the number of entries on the RHS of the IN operator ** M = the number of rows in the table that match terms to the ** to the left in the same index. If the IN operator is on @@ -2491,11 +2491,12 @@ ** If we do not have real sqlite_stat1 data, always prefer to use ** the index. */ M = pProbe->aiRowLogEst[saved_nEq]; logK = estLog(nIn); - if( M + logK + 10 < nIn + rLogSize ){ + safetyMargin = 10; /* TUNING: extra weight for indexed IN */ + if( M + logK + safetyMargin < nIn + rLogSize ){ WHERETRACE(0x40, ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n", saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize)); continue; }else{