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

@ -1,5 +1,5 @@
C Query\splanner\stuning:\s\sIncrease\sthe\smaximum\snumber\sof\ssimultaneous\ssolutions\nto\strack\sint\seh\ssolver\sfrom\s10\sto\s12.
D 2024-05-28T00:01:07.835
C Improve\sthe\sautomatic-index\sdecision\ssuch\sthat\sno\sattempt\sis\smade\sto\screate\nan\sautomatic\sindex\son\sa\scolumn\sthat\sis\sknown\sto\sbe\snon-selective\sbecause\sif\nits\suse\sin\sother\sindexes\sthat\shave\sbeen\sanalyzed.\s\sSee\n[src:/tktview/8ff324e120|ticket\s8ff324e120]\sand\n[forum:/forumpost/b21c2101a559be0a|forum\spost\sb21c2101a559be0a].
D 2024-05-28T00:16:52.505
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -840,7 +840,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 887fc4ca3f020ebb2e376f222069570834ac63bf50111ef0cbf3ae417048ed89
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
F src/where.c dd7d9eb570c35caf94797814f9d54b187175bd21966f7f4dfd36b0c1f63aa501
F src/where.c ad4866c036a9d64f0c79ccf2ec60ac65bb64cb81b9facce453b0a920caac7a1d
F src/whereInt.h 82a13766f13d1a53b05387c2e60726289ef26404bc7b9b1f7770204d97357fb8
F src/wherecode.c d5184620bcb5265d59072cb66e1386bfe0331a9ce7614286f9ab79a4fcd00fb8
F src/whereexpr.c 67d15caf88a1a9528283d68ff578e024cf9fe810b517bb0343e5aaf695ad97dd
@ -910,7 +910,7 @@ F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e188
F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39
F test/autoindex1.test d34caffb0384003ee28eae87679214c029e9be4b332d9649a79e0b94ab70502c
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test dcd6b2f8bed2be67b131e2e671f892e971d934e24fd00988952d0e0a67e24aa7
F test/autoindex3.test ca502c8050166ac6107a7b4fe4e951f4d3270a23a958af02b14f1b962b83c4b6
F test/autoindex4.test 3c2105e9172920e26f950ba3c5823e4972190e022c1e6f260ba476b0af24c593
F test/autoindex5.test 2ee94f033b87ca0160e08d81034c507aff8e230df2627f0304fa309b2fee19a3
F test/autovacuum.test 00671369bbf96c6a49989a9425f5b78b94075d6a4b031e5e00000c2c32f365df
@ -2193,8 +2193,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 1b6d1fbcdecf14bc79dc7b5df50e585d2fcc1484a9987b863c190e8f7ba2c39f
R 81c36ec13694e48008fb110fd73a5f00
P fe2e1dadbacbe6392ceed44fd287a2ed82189cb8055f35631d37967d9a7a5d1d 70409763f70faa2a0f4f072fd318a687b109a0905cc57906ad7f80d2885fe6d9
R a2e2cddff59ec6ba73015ce8c07a73b7
T +closed 70409763f70faa2a0f4f072fd318a687b109a0905cc57906ad7f80d2885fe6d9
U drh
Z 108dc3aeba08b8d2b68875bf68eaf849
Z 8ce1e608e60c39ba63116e451ee082d8
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
fe2e1dadbacbe6392ceed44fd287a2ed82189cb8055f35631d37967d9a7a5d1d
2a7603c327d11d5e6bc4d40c29151fea544d650f51200ff76efb921adb0c38df

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

View File

@ -90,5 +90,40 @@ do_eqp_test 220 {
`--SEARCH u USING AUTOMATIC COVERING INDEX (b=?)
}
# 2024-05-27
# ticket https://sqlite.org/src/tktview/8ff324e120
# forum post https://sqlite.org/forum/forumpost/b21c2101a559be0a
#
# If an index with STAT1 data indicates that a column is not very
# selective, then do not attempt to create an automatic index on
# that column.
#
reset_db
do_execsql_test 300 {
CREATE TABLE t1(id INTEGER PRIMARY KEY);
CREATE TABLE t2(cid INT, pid INT, rx INT, PRIMARY KEY(cid, pid, rx));
CREATE INDEX x1 ON t2(pid, rx);
ANALYZE sqlite_schema;
REPLACE INTO sqlite_stat1(tbl, idx, stat) VALUES
('t2', 'x1', '500000 250 250'),
('t2','sqlite_autoindex_t2_1','500000 1 1 1');
ANALYZE sqlite_schema;
}
do_eqp_test 310 {
WITH RECURSIVE children(id) AS (
SELECT cid FROM t2 WHERE pid = ?1 AND rx = ?2
UNION
SELECT cid FROM t2 JOIN children ON t2.pid = children.id AND rx = ?2
) SELECT count(id) FROM children;
} {
QUERY PLAN
|--CO-ROUTINE children
| |--SETUP
| | `--SEARCH t2 USING INDEX x1 (pid=? AND rx=?)
| `--RECURSIVE STEP
| |--SCAN children
| `--SEARCH t2 USING INDEX x1 (pid=? AND rx=?)
`--SCAN children
}
finish_test