From: drh <> Date: Fri, 10 Feb 2023 21:53:33 +0000 (+0000) Subject: Do a better job of detecting when a WHERE clause term might be useful to X-Git-Tag: version-3.41.0~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=80e936aef00ab05fa8863c2e72244d08fa3fa71e;p=thirdparty%2Fsqlite.git Do a better job of detecting when a WHERE clause term might be useful to an expression index. Fix for performance regression reported by [forum:/forumpost/e65800d8cb|forum thread e65800d8cb]. FossilOrigin-Name: 44200596aa943963bc6ca98b5d4fd5b9235d1109d8dfc1a75eeae353b4239142 --- diff --git a/manifest b/manifest index 1167feb4a9..0e777dd8cb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sthe\sfts5\strigram\stokenizer\sand\sLIKE\sor\sGLOB\spatterns\sfor\swhich\scontain\sruns\sof\s2\sor\sfewer\snon-wildcard\scharacters\sthat\sare\s3\sor\smore\sbytes\swhen\sencoded\sas\sutf-8. -D 2023-02-10T17:17:04.066 +C Do\sa\sbetter\sjob\sof\sdetecting\swhen\sa\sWHERE\sclause\sterm\smight\sbe\suseful\sto\nan\sexpression\sindex.\s\sFix\sfor\sperformance\sregression\sreported\sby\n[forum:/forumpost/e65800d8cb|forum\sthread\se65800d8cb]. +D 2023-02-10T21:53:33.465 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -709,7 +709,7 @@ F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b F src/where.c 5b20d08699c9a55c0556661ff6f937dd1c8e27567b7553e48d477d3fad22ec4c F src/whereInt.h e25203e5bfee149f5f1225ae0166cfb4f1e65490c998a024249e98bb0647377c F src/wherecode.c 76bca3379219880d2527493b71a3be49e696f75396d3481e4de5d4ceec7886b2 -F src/whereexpr.c 7c5671a04b00c876bec5e99fd4e6f688065feb4773160fbf76fd7900d2901777 +F src/whereexpr.c aa9467272033315424c76f446ca0b65683d6002ededaa65b6a6d4c00b3b525b8 F src/window.c 76a27cff9ea2ded0c2c3527187029259440fabcc4cc4c07b11d942c78494a614 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1884,7 +1884,7 @@ F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test c4bb7e2ca56d49bd8ab5c7bd085b8b83e353922b46904d68aefb3c7468643581 F test/whereJ.test fc05e374cc9f2dc204148d6c06822c380ad388895fe97a6d335b94a26a08aecf F test/whereK.test 0270ab7f04ba5436fb9156d31d642a1c82727f4c4bfe5ba90d435c78cf44684a -F test/whereL.test 50171e3ec00b4c8ad5ec773119a35d9e9642cec45154b44c366d628326479f4d +F test/whereL.test 9d7c8a9f4e5e82d6859e61cf8758c3856c7e0a7fd8be11c92cac8c3ec39228fd F test/whereM.test 0dbc9998783458ddcf3cc078ca7c2951d8b2677d472ecf0028f449ed327c0250 F test/wherefault.test 6cf2a9c5712952d463d3f45ebee7f6caf400984df51a195d884cfb7eb0e837a7 F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3 @@ -2045,8 +2045,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 734766451123c98a467c3407562eaa097b3307c8a275e1c8dd93e4654fe78014 -R 5bf915f087ec1f7e7765a72585c21ed1 -U dan -Z 46cdaf9bdec2b8801443f3e6fa3042be +P 00714b39b39c51519edbc0194f98c7275fecf96763a06fd95db6e1d81bb9f1f1 +R 122a35632c84f1a86bc1efeb49e3bb37 +U drh +Z 7d2b0fd613ff6bddf59b196d4f5df2a1 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c8148f1b18..2fbc826de3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -00714b39b39c51519edbc0194f98c7275fecf96763a06fd95db6e1d81bb9f1f1 \ No newline at end of file +44200596aa943963bc6ca98b5d4fd5b9235d1109d8dfc1a75eeae353b4239142 \ No newline at end of file diff --git a/src/whereexpr.c b/src/whereexpr.c index b466c2da2e..0be39b7d6a 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -974,36 +974,38 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ */ static SQLITE_NOINLINE int exprMightBeIndexed2( SrcList *pFrom, /* The FROM clause */ - Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */ int *aiCurCol, /* Write the referenced table cursor and column here */ - Expr *pExpr /* An operand of a comparison operator */ + Expr *pExpr, /* An operand of a comparison operator */ + int j /* Start looking with the j-th pFrom entry */ ){ Index *pIdx; int i; int iCur; - for(i=0; mPrereq>1; i++, mPrereq>>=1){} - iCur = pFrom->a[i].iCursor; - for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ - if( pIdx->aColExpr==0 ) continue; - for(i=0; inKeyCol; i++){ - if( pIdx->aiColumn[i]!=XN_EXPR ) continue; - assert( pIdx->bHasExpr ); - if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ - aiCurCol[0] = iCur; - aiCurCol[1] = XN_EXPR; - return 1; + do{ + iCur = pFrom->a[j].iCursor; + for(pIdx=pFrom->a[j].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->aColExpr==0 ) continue; + for(i=0; inKeyCol; i++){ + if( pIdx->aiColumn[i]!=XN_EXPR ) continue; + assert( pIdx->bHasExpr ); + if( sqlite3ExprCompareSkip(pExpr,pIdx->aColExpr->a[i].pExpr,iCur)==0 ){ + aiCurCol[0] = iCur; + aiCurCol[1] = XN_EXPR; + return 1; + } } } - } + }while( ++j < pFrom->nSrc ); return 0; } static int exprMightBeIndexed( SrcList *pFrom, /* The FROM clause */ - Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */ int *aiCurCol, /* Write the referenced table cursor & column here */ Expr *pExpr, /* An operand of a comparison operator */ int op /* The specific comparison operator */ ){ + int i; + /* If this expression is a vector to the left or right of a ** inequality constraint (>, <, >= or <=), perform the processing ** on the first element of the vector. */ @@ -1013,7 +1015,6 @@ static int exprMightBeIndexed( if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){ assert( ExprUseXList(pExpr) ); pExpr = pExpr->x.pList->a[0].pExpr; - } if( pExpr->op==TK_COLUMN ){ @@ -1021,9 +1022,16 @@ static int exprMightBeIndexed( aiCurCol[1] = pExpr->iColumn; return 1; } - if( mPrereq==0 ) return 0; /* No table references */ - if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */ - return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr); + + for(i=0; inSrc; i++){ + Index *pIdx; + for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + if( pIdx->aColExpr ){ + return exprMightBeIndexed2(pFrom,aiCurCol,pExpr,i); + } + } + } + return 0; } @@ -1149,7 +1157,7 @@ static void exprAnalyze( pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr; } - if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){ + if( exprMightBeIndexed(pSrc, aiCurCol, pLeft, op) ){ pTerm->leftCursor = aiCurCol[0]; assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); pTerm->u.x.leftColumn = aiCurCol[1]; @@ -1157,7 +1165,7 @@ static void exprAnalyze( } if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; if( pRight - && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op) + && exprMightBeIndexed(pSrc, aiCurCol, pRight, op) && !ExprHasProperty(pRight, EP_FixedCol) ){ WhereTerm *pNew; diff --git a/test/whereL.test b/test/whereL.test index b6f86fc2d2..c3bdcb8f34 100644 --- a/test/whereL.test +++ b/test/whereL.test @@ -189,5 +189,24 @@ do_execsql_test 610 { AND A.RunYearMonth = B.RunYearMonth; } {4 202004 4 202004 5 202004 5 202004} +# 2023-02-10 https://sqlite.org/forum/forumpost/0a539c76db3b9e29 +# The original constant propagation implementation caused a performance +# regression. Because "abs(v)" was rewritten into "abs(1)" it no longer +# matches the indexed column and the index is not used. +# +reset_db +do_execsql_test 700 { + CREATE TABLE t1(v INTEGER); + WITH RECURSIVE c(x) AS (VALUES(-10) UNION ALL SELECT x+1 FROM c WHERE x<10) + INSERT INTO t1(v) SELECT x FROM c; + CREATE INDEX idx ON t1( abs(v) ); + SELECT v FROM t1 WHERE abs(v)=1 and v=1; +} 1 +do_eqp_test 710 { + SELECT v FROM t1 WHERE abs(v)=1 and v=1; +} { + QUERY PLAN + `--SEARCH t1 USING INDEX idx (=?) +} finish_test