mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
When the estimated cost to do a sort overwhelms the estimated cost to do
individual table lookups, make sure that the table lookup costs are still taken into consideration when selecting the lookup algorithm. FossilOrigin-Name: ec5d84ba69c100d9565425ed74040a49e410ea03
This commit is contained in:
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
|||||||
C A\scouple\smore\sharmless\scompiler\swarnings\seliminated.
|
C When\sthe\sestimated\scost\sto\sdo\sa\ssort\soverwhelms\sthe\sestimated\scost\sto\sdo\nindividual\stable\slookups,\smake\ssure\sthat\sthe\stable\slookup\scosts\sare\sstill\ntaken\sinto\sconsideration\swhen\sselecting\sthe\slookup\salgorithm.
|
||||||
D 2014-08-06T18:50:51.299
|
D 2014-08-07T16:50:00.581
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -296,7 +296,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
|||||||
F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a
|
F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||||
F src/where.c ce1b9a3a2573033cd15e0882719db7f211f21cdd
|
F src/where.c 5a099c6d2a1bfbf46bc64979e89330dee3a1f3b9
|
||||||
F src/whereInt.h 929c1349b5355fd44f22cee5c14d72b3329c58a6
|
F src/whereInt.h 929c1349b5355fd44f22cee5c14d72b3329c58a6
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
@ -1117,7 +1117,7 @@ F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
|||||||
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
||||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||||
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
|
||||||
F test/whereJ.test 7dde28284d20f358b559ca592e294db03e1d7103
|
F test/whereJ.test 35a40a50d0e13aa6b0de7cc5d4b204e5f9f9669f
|
||||||
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||||
@ -1185,7 +1185,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P a2a60307ea68a3230952a56cb65369ba0a208967
|
P bcf6d775f90f4d1ba018a1b965f2f710df130f01
|
||||||
R 1442001d079992194e2cf55642b869fa
|
R da285ec7c1bbef437389fa691998cee0
|
||||||
U drh
|
U drh
|
||||||
Z bb5786216c21ae2a69b537cdb50bf939
|
Z 083887f7ebac8cb5fec0c6d1cdc7c751
|
||||||
|
@ -1 +1 @@
|
|||||||
bcf6d775f90f4d1ba018a1b965f2f710df130f01
|
ec5d84ba69c100d9565425ed74040a49e410ea03
|
37
src/where.c
37
src/where.c
@ -5424,6 +5424,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
LogEst rCost; /* Cost of a path */
|
LogEst rCost; /* Cost of a path */
|
||||||
LogEst nOut; /* Number of outputs */
|
LogEst nOut; /* Number of outputs */
|
||||||
LogEst mxCost = 0; /* Maximum cost of a set of paths */
|
LogEst mxCost = 0; /* Maximum cost of a set of paths */
|
||||||
|
LogEst mxOut = 0; /* nOut value for maximum cost path */
|
||||||
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
|
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
|
||||||
WherePath *aFrom; /* All nFrom paths at the previous level */
|
WherePath *aFrom; /* All nFrom paths at the previous level */
|
||||||
WherePath *aTo; /* The nTo best paths at the current level */
|
WherePath *aTo; /* The nTo best paths at the current level */
|
||||||
@ -5441,7 +5442,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
** For joins of 3 or more tables, track the 10 best paths */
|
** For joins of 3 or more tables, track the 10 best paths */
|
||||||
mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
|
mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
|
||||||
assert( nLoop<=pWInfo->pTabList->nSrc );
|
assert( nLoop<=pWInfo->pTabList->nSrc );
|
||||||
WHERETRACE(0x002, ("---- begin solver\n"));
|
WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d)\n", nRowEst));
|
||||||
|
|
||||||
/* Allocate and initialize space for aTo and aFrom */
|
/* Allocate and initialize space for aTo and aFrom */
|
||||||
ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
|
ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
|
||||||
@ -5529,7 +5530,13 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
}else{
|
}else{
|
||||||
revMask = pFrom->revLoop;
|
revMask = pFrom->revLoop;
|
||||||
}
|
}
|
||||||
/* Check to see if pWLoop should be added to the mxChoice best so far */
|
/* Check to see if pWLoop should be added to the set of
|
||||||
|
** mxChoice best-so-far paths.
|
||||||
|
**
|
||||||
|
** First look for an existing path among best-so-far paths
|
||||||
|
** that covers the same set of loops and has the same isOrdered
|
||||||
|
** setting as the current path candidate.
|
||||||
|
*/
|
||||||
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
|
for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
|
||||||
if( pTo->maskLoop==maskNew
|
if( pTo->maskLoop==maskNew
|
||||||
&& ((pTo->isOrdered^isOrdered)&80)==0
|
&& ((pTo->isOrdered^isOrdered)&80)==0
|
||||||
@ -5539,7 +5546,14 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( jj>=nTo ){
|
if( jj>=nTo ){
|
||||||
if( nTo>=mxChoice && rCost>=mxCost ){
|
/* None of the existing best-so-far paths match the candidate. */
|
||||||
|
if( nTo>=mxChoice && rCost==mxCost ) printf("nOut=%d mxOut=%d\n", nOut, mxOut);
|
||||||
|
if( nTo>=mxChoice
|
||||||
|
&& (rCost>mxCost || (rCost==mxCost && nOut>=mxOut))
|
||||||
|
){
|
||||||
|
/* The current candidate is no better than any of the mxChoice
|
||||||
|
** paths currently in the best-so-far buffer. So discard
|
||||||
|
** this candidate as not viable. */
|
||||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||||
if( sqlite3WhereTrace&0x4 ){
|
if( sqlite3WhereTrace&0x4 ){
|
||||||
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
|
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
|
||||||
@ -5549,7 +5563,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Add a new Path to the aTo[] set */
|
/* If we reach this points it means that the new candidate path
|
||||||
|
** needs to be added to the set of best-so-far paths. */
|
||||||
if( nTo<mxChoice ){
|
if( nTo<mxChoice ){
|
||||||
/* Increase the size of the aTo set by one */
|
/* Increase the size of the aTo set by one */
|
||||||
jj = nTo++;
|
jj = nTo++;
|
||||||
@ -5566,7 +5581,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}else{
|
}else{
|
||||||
if( pTo->rCost<=rCost ){
|
/* Control reaches here if best-so-far path pTo=aTo[jj] covers the
|
||||||
|
** same set of loops and has the sam isOrdered setting as the
|
||||||
|
** candidate path. Check to see if the candidate should replace
|
||||||
|
** pTo or if the candidate should be skipped */
|
||||||
|
if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
|
||||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||||
if( sqlite3WhereTrace&0x4 ){
|
if( sqlite3WhereTrace&0x4 ){
|
||||||
sqlite3DebugPrintf(
|
sqlite3DebugPrintf(
|
||||||
@ -5578,11 +5597,13 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
/* Discard the candidate path from further consideration */
|
||||||
testcase( pTo->rCost==rCost );
|
testcase( pTo->rCost==rCost );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
testcase( pTo->rCost==rCost+1 );
|
testcase( pTo->rCost==rCost+1 );
|
||||||
/* A new and better score for a previously created equivalent path */
|
/* Control reaches here if the candidate path is better than the
|
||||||
|
** pTo path. Replace pTo with the candidate. */
|
||||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||||
if( sqlite3WhereTrace&0x4 ){
|
if( sqlite3WhereTrace&0x4 ){
|
||||||
sqlite3DebugPrintf(
|
sqlite3DebugPrintf(
|
||||||
@ -5606,9 +5627,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
|||||||
if( nTo>=mxChoice ){
|
if( nTo>=mxChoice ){
|
||||||
mxI = 0;
|
mxI = 0;
|
||||||
mxCost = aTo[0].rCost;
|
mxCost = aTo[0].rCost;
|
||||||
|
mxOut = aTo[0].nRow;
|
||||||
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
|
for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
|
||||||
if( pTo->rCost>mxCost ){
|
if( pTo->rCost>mxCost || (pTo->rCost==mxCost && pTo->nRow>mxOut) ){
|
||||||
mxCost = pTo->rCost;
|
mxCost = pTo->rCost;
|
||||||
|
mxOut = pTo->nRow;
|
||||||
mxI = jj;
|
mxI = jj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
#
|
#
|
||||||
# This file implements a single regression test for a complex
|
# This file implements regression tests for a complex
|
||||||
# query planning case.
|
# query planning case.
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -328,4 +328,48 @@ do_execsql_test whereJ-1.4 {
|
|||||||
GROUP BY aid;
|
GROUP BY aid;
|
||||||
} {/B-TREE/}
|
} {/B-TREE/}
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
# Ensure that the sorting cost does not swamp the loop costs and cause
|
||||||
|
# distinctions between individual loop costs to get lost, and hence for
|
||||||
|
# sub-optimal loops to be chosen.
|
||||||
|
#
|
||||||
|
do_execsql_test whereJ-2.1 {
|
||||||
|
CREATE TABLE tab(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
minChild INTEGER REFERENCES t1,
|
||||||
|
maxChild INTEGER REFERENCES t1,
|
||||||
|
x INTEGER
|
||||||
|
);
|
||||||
|
EXPLAIN QUERY PLAN
|
||||||
|
SELECT t4.x
|
||||||
|
FROM tab AS t0, tab AS t1, tab AS t2, tab AS t3, tab AS t4
|
||||||
|
WHERE t0.id=0
|
||||||
|
AND t1.id BETWEEN t0.minChild AND t0.maxChild
|
||||||
|
AND t2.id BETWEEN t1.minChild AND t1.maxChild
|
||||||
|
AND t3.id BETWEEN t2.minChild AND t2.maxChild
|
||||||
|
AND t4.id BETWEEN t3.minChild AND t3.maxChild
|
||||||
|
ORDER BY t4.x;
|
||||||
|
} {~/SCAN/}
|
||||||
|
do_execsql_test whereJ-2.2 {
|
||||||
|
EXPLAIN QUERY PLAN
|
||||||
|
SELECT t4.x
|
||||||
|
FROM tab AS t0a, tab AS t0b,
|
||||||
|
tab AS t1a, tab AS t1b,
|
||||||
|
tab AS t2a, tab AS t2b,
|
||||||
|
tab AS t3a, tab AS t3b,
|
||||||
|
tab AS t4
|
||||||
|
WHERE 1
|
||||||
|
AND t0a.id=1
|
||||||
|
AND t1a.id BETWEEN t0a.minChild AND t0a.maxChild
|
||||||
|
AND t2a.id BETWEEN t1a.minChild AND t1a.maxChild
|
||||||
|
AND t3a.id BETWEEN t2a.minChild AND t2a.maxChild
|
||||||
|
AND t0b.id=2
|
||||||
|
AND t1b.id BETWEEN t0b.minChild AND t0b.maxChild
|
||||||
|
AND t2b.id BETWEEN t1b.minChild AND t1b.maxChild
|
||||||
|
AND t3b.id BETWEEN t2b.minChild AND t2b.maxChild
|
||||||
|
AND t4.id BETWEEN t3a.minChild AND t3b.maxChild
|
||||||
|
ORDER BY t4.x;
|
||||||
|
} {~/SCAN/}
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
Reference in New Issue
Block a user