1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Improve the automatic-index decision such that no attempt is made to create

an automatic index on a column that is known to be non-selective because if
its use in other indexes that have been analyzed.  See
[src:/tktview/8ff324e120|ticket 8ff324e120] and
[forum:/forumpost/b21c2101a559be0a|forum post b21c2101a559be0a].

FossilOrigin-Name: 2a7603c327d11d5e6bc4d40c29151fea544d650f51200ff76efb921adb0c38df
This commit is contained in:
drh
2024-05-28 00:16:52 +00:00
4 changed files with 84 additions and 11 deletions

View File

@ -840,6 +840,40 @@ static int constraintCompatibleWithOuterJoin(
return 1;
}
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
** Return true if column iCol of table pTab seem like it might be a
** good column to use as part of a query-time index.
**
** Current algorithm (subject to improvement!):
**
** 1. If iCol is already the left-most column of some other index,
** then return false.
**
** 2. If iCol is part of an existing index that has an aiRowLogEst of
** more than 20, then return false.
**
** 3. If no disqualifying conditions above are found, return true.
*/
static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
const Table *pTab,
int iCol
){
const Index *pIdx;
for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){
int j;
for(j=0; j<pIdx->nKeyCol; j++){
if( pIdx->aiColumn[j]==iCol ){
if( j==0 ) return 0;
if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0;
break;
}
}
}
return 1;
}
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@ -854,6 +888,8 @@ static int termCanDriveIndex(
const Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
int leftCol;
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
@ -864,11 +900,12 @@ static int termCanDriveIndex(
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
if( pTerm->u.x.leftColumn<0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
leftCol = pTerm->u.x.leftColumn;
if( leftCol<0 ) return 0;
aff = pSrc->pTab->aCol[leftCol].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
return 1;
return columnIsGoodIndexCandidate(pSrc->pTab, leftCol);
}
#endif