]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Further refinement of the idea of multiplying run-time cost estimates by
authordrh <drh@noemail.net>
Tue, 8 Oct 2013 18:40:37 +0000 (18:40 +0000)
committerdrh <drh@noemail.net>
Tue, 8 Oct 2013 18:40:37 +0000 (18:40 +0000)
the estimated row size.

FossilOrigin-Name: 18bd6ba96d19de6047baebfa15b1f739577c9ec4

manifest
manifest.uuid
src/build.c
src/select.c
src/where.c
test/e_select.test
test/where9.test

index 623db16001a173f6573a5039c9043a37e70b9b5d..3f72457301c538e79a9d42899808126564d7b458 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Multiply\sall\scursor\sstep\scost\sestimates\sby\sthe\sestimated\ssize\sof\sthe\srow\sin\nbytes,\sin\sorder\sto\sget\sthe\squery\splanner\sot\smake\suse\sof\sestimated\srow\ssizes.\nThis\scheck-in\suses\smagic\snumbers\sin\sa\sfew\splaces\s(for\sexample,\sestimates\sof\nthe\ssize\sof\soutput\srows)\sand\sneeds\slots\sof\srefinement.\s\sConsider\sthis\sa\nproof-of-concept\sonly.
-D 2013-10-07T17:32:15.338
+C Further\srefinement\sof\sthe\sidea\sof\smultiplying\srun-time\scost\sestimates\sby\nthe\sestimated\srow\ssize.
+D 2013-10-08T18:40:37.532
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -166,7 +166,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
 F src/btree.c d5720cbb21ae56e7e5b07847e05e5b203818acac
 F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
 F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
-F src/build.c ea07ec35354cdcd017b128679391320220030336
+F src/build.c 3da02c07b0f198a11ce3766cd34eac311656f1e8
 F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
@@ -216,7 +216,7 @@ F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
 F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
 F src/resolve.c 7459801d02997b07e8b8da85ef255392ba1d022b
 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
-F src/select.c 13be733297f415b388444a2e296d23569cd83b8a
+F src/select.c 9d111a1adef56151b4bbddbcaea6d117d374e17d
 F src/shell.c 5ee50ca3e35453bbd6ccdf1bdd0f6bbe9738e9fb
 F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5
 F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
@@ -290,7 +290,7 @@ F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
 F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
-F src/where.c ad5e680c0b95014bb9e227990d6b0efe634e7749
+F src/where.c 2a04ab5856f8c964369d181f3580a8d14e4a325c
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -437,7 +437,7 @@ F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
 F test/e_insert.test 291e056e1a442a5e5166a989a8a03a46e38225ca
 F test/e_reindex.test e175794fc41f8e8aef34772e87a7d7b7a9251dd3
 F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
-F test/e_select.test f2358d074bd82240bc79a8348f284a2a8909dc1f
+F test/e_select.test d3226cb94fae4af3f198e68e71f655e106d0be47
 F test/e_select2.test 22c660a7becf0712c95e1ca1b2d9e716a1261460
 F test/e_update.test bea00499e43ee1da77b03cdb0b20c7c864c1ec5a
 F test/e_uri.test a2c92d80093a7efdcfbb11093651cbea87097b6b
@@ -1059,7 +1059,7 @@ F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
 F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
 F test/where8.test 6f95896633cf2d307b5263145b942b7d33e837c6
 F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
-F test/where9.test 4f3eab951353a3ae164befc521c777dfa903e46c
+F test/where9.test 06c5f1e13168239951d2426078334d97fdf2d26f
 F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
 F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
 F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
@@ -1121,7 +1121,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 1d7b2dc0eae70c0c0e523b715acf758bb4cfa9ac
-R b3d2afdb618d61f33659270b34382478
+P cb34cfe57c2a664fbfae8106e95114400ea222d5
+R 2b7915a92bd0315e781ed0d1390f4f69
 U drh
-Z 2fed1ec905830e828c488397bcac95d0
+Z 27bbb4f4b3fe1d2932c4d2e467493b71
index b45f4b6ece886bd3433f1ca6b0d50fcf2b115912..d8fa3b1ba2c7dc046b2335a990a3d1b9e5567038 100644 (file)
@@ -1 +1 @@
-cb34cfe57c2a664fbfae8106e95114400ea222d5
\ No newline at end of file
+18bd6ba96d19de6047baebfa15b1f739577c9ec4
\ No newline at end of file
index 3c8d22d3cdfc57a6f91dda5bc4e19862b4b16b4c..e14988ae1f2894c61224e692ef7aabdf5f70b022 100644 (file)
@@ -879,7 +879,7 @@ void sqlite3StartTable(
   pTable->iPKey = -1;
   pTable->pSchema = db->aDb[iDb].pSchema;
   pTable->nRef = 1;
-  pTable->nRowEst = 1000000;
+  pTable->nRowEst = 1048576;
   assert( pParse->pNewTable==0 );
   pParse->pNewTable = pTable;
 
index f9c7835fd27315a08e9b43fb90233e02cbc1241a..cbf8e14cf3fb6b03032fdbd3b8248116c442fb7f 100644 (file)
@@ -1424,8 +1424,7 @@ static int selectColumnsFromExprList(
 */
 static void selectAddColumnTypeAndCollation(
   Parse *pParse,        /* Parsing contexts */
-  int nCol,             /* Number of columns */
-  Column *aCol,         /* List of columns */
+  Table *pTab,          /* Add column type information to this table */
   Select *pSelect       /* SELECT used to determine types and collations */
 ){
   sqlite3 *db = pParse->db;
@@ -1435,17 +1434,20 @@ static void selectAddColumnTypeAndCollation(
   int i;
   Expr *p;
   struct ExprList_item *a;
+  u64 szAll = 0;
 
   assert( pSelect!=0 );
   assert( (pSelect->selFlags & SF_Resolved)!=0 );
-  assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
+  assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
   if( db->mallocFailed ) return;
   memset(&sNC, 0, sizeof(sNC));
   sNC.pSrcList = pSelect->pSrc;
   a = pSelect->pEList->a;
-  for(i=0, pCol=aCol; i<nCol; i++, pCol++){
+  for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
     p = a[i].pExpr;
     pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
+    sqlite3AffinityType(pCol->zType, &pCol->szEst);
+    szAll += pCol->szEst;
     pCol->affinity = sqlite3ExprAffinity(p);
     if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
     pColl = sqlite3ExprCollSeq(pParse, p);
@@ -1453,6 +1455,7 @@ static void selectAddColumnTypeAndCollation(
       pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
     }
   }
+  pTab->szTabRow = sqlite3LogEst(szAll*4);
 }
 
 /*
@@ -1480,9 +1483,9 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
   assert( db->lookaside.bEnabled==0 );
   pTab->nRef = 1;
   pTab->zName = 0;
-  pTab->nRowEst = 1000000;
+  pTab->nRowEst = 1048576;
   selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
-  selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
+  selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
   pTab->iPKey = -1;
   if( db->mallocFailed ){
     sqlite3DeleteTable(db, pTab);
@@ -3394,11 +3397,11 @@ static int selectExpander(Walker *pWalker, Select *p){
       pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
       if( pTab==0 ) return WRC_Abort;
       pTab->nRef = 1;
-      pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
+      pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
       while( pSel->pPrior ){ pSel = pSel->pPrior; }
       selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
       pTab->iPKey = -1;
-      pTab->nRowEst = 1000000;
+      pTab->nRowEst = 1048576;
       pTab->tabFlags |= TF_Ephemeral;
 #endif
     }else{
@@ -3682,7 +3685,7 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
         Select *pSel = pFrom->pSelect;
         assert( pSel );
         while( pSel->pPrior ) pSel = pSel->pPrior;
-        selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
+        selectAddColumnTypeAndCollation(pParse, pTab, pSel);
       }
     }
   }
index 3cf09a81797920c5448f691ac5bb56f3f5d6ce49..b576d4f2b730630a66663a224ebf2145b5e79785 100644 (file)
@@ -2450,15 +2450,15 @@ static int whereRangeScanEst(
   WhereLoopBuilder *pBuilder,
   WhereTerm *pLower,   /* Lower bound on the range. ex: "x>123" Might be NULL */
   WhereTerm *pUpper,   /* Upper bound on the range. ex: "x<455" Might be NULL */
-  LogEst *pnOut        /* IN/OUT: Number of rows visited */
+  WhereLoop *pLoop     /* Modify the .nOut and maybe .rRun fields */
 ){
   int rc = SQLITE_OK;
-  int nOut = (int)*pnOut;
+  int nOut = pLoop->nOut;
+  int nEq = pLoop->u.btree.nEq;
   LogEst nNew;
 
 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
-  Index *p = pBuilder->pNew->u.btree.pIndex;
-  int nEq = pBuilder->pNew->u.btree.nEq;
+  Index *p = pLoop->u.btree.pIndex;
 
   if( p->nSample>0
    && nEq==pBuilder->nRecValid
@@ -2546,7 +2546,7 @@ static int whereRangeScanEst(
       if( nNew<nOut ){
         nOut = nNew;
       }
-      *pnOut = (LogEst)nOut;
+      pLoop->nOut = (LogEst)nOut;
       WHERETRACE(0x100, ("range scan regions: %u..%u  est=%d\n",
                          (u32)iLower, (u32)iUpper, nOut));
       return SQLITE_OK;
@@ -2570,7 +2570,7 @@ static int whereRangeScanEst(
   }
   if( nNew<10 ) nNew = 10;
   if( nNew<nOut ) nOut = nNew;
-  *pnOut = (LogEst)nOut;
+  pLoop->nOut = (LogEst)nOut;
   return rc;
 }
 
@@ -4337,7 +4337,13 @@ static int whereLoopAddBtreeIndex(
     if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
       /* Adjust nOut and rRun for STAT3 range values */
       assert( pNew->nOut==saved_nOut );
-      whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
+      whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
+
+      /* If the range constraint is the only constraint on the index and
+      ** if the range constraint does not reduce the search space,
+      ** then this is really just an index scan which has already
+      ** been analyzed. */
+      if( pNew->nOut>=saved_nOut && pNew->u.btree.nEq==0 ) continue;
     }
 #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
     if( nInMul==0 
@@ -4816,6 +4822,8 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
   pWCEnd = pWC->a + pWC->nTerm;
   pNew = pBuilder->pNew;
   memset(&sSum, 0, sizeof(sSum));
+  pItem = pWInfo->pTabList->a + pNew->iTab;
+  iCur = pItem->iCursor;
 
   for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
     if( (pTerm->eOperator & WO_OR)!=0
@@ -4827,8 +4835,6 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
       int once = 1;
       int i, j;
     
-      pItem = pWInfo->pTabList->a + pNew->iTab;
-      iCur = pItem->iCursor;
       sSubBuild = *pBuilder;
       sSubBuild.pOrderBy = 0;
       sSubBuild.pOrSet = &sCur;
@@ -5266,8 +5272,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
   if( pWInfo->pOrderBy==0 || nRowEst==0 ){
     aFrom[0].isOrderedValid = 1;
   }else{
-    /* TUNING: Estimated cost of sorting is N*log2(N) where N is the
-    ** number of output rows. */
+    /* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
+    ** number of output rows. The 48 is the expected size of a row to sort. 
+    ** FIXME:  compute a better estimate of the 48 multiplier based on the
+    ** result set expressions. */
     rSortCost = nRowEst + estLog(nRowEst) + 55;
     WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
   }
index 108b6b1540f85003891afc3581685a6abbc1d4c8..61646a2a3131fad33547cc0e5b47a2fe3b8656fb 100644 (file)
@@ -450,17 +450,17 @@ do_join_test e_select-1.4.1.4 {
 # left-hand and right-hand datasets.
 #
 do_join_test e_select-1.4.2.1 {
-  SELECT * FROM x2 %JOIN% x3
+  SELECT * FROM x2 %JOIN% x3 ORDER BY +c, +f
 } [list -60.06 {} {}      -39.24 {} encompass -1                 \
-        -60.06 {} {}      presenting 51 reformation dignified    \
-        -60.06 {} {}      conducting -87.24 37.56 {}             \
-        -60.06 {} {}      coldest -96 dramatists 82.3            \
         -60.06 {} {}      alerting {} -93.79 {}                  \
+        -60.06 {} {}      coldest -96 dramatists 82.3            \
+        -60.06 {} {}      conducting -87.24 37.56 {}             \
+        -60.06 {} {}      presenting 51 reformation dignified    \
         -58 {} 1.21       -39.24 {} encompass -1                 \
-        -58 {} 1.21       presenting 51 reformation dignified    \
-        -58 {} 1.21       conducting -87.24 37.56 {}             \
-        -58 {} 1.21       coldest -96 dramatists 82.3            \
         -58 {} 1.21       alerting {} -93.79 {}                  \
+        -58 {} 1.21       coldest -96 dramatists 82.3            \
+        -58 {} 1.21       conducting -87.24 37.56 {}             \
+        -58 {} 1.21       presenting 51 reformation dignified    \
 ]
 # TODO: Come back and add a few more like the above.
 
index 1c32ff82f7b9f8e25eee2cd2e43919da2c89b598..963d3bc1b72ba029aca022845df74a6656e0dce0 100644 (file)
@@ -781,27 +781,7 @@ do_test where9-6.8.2 {
         OR (b NOT NULL AND c NOT NULL AND d IS NULL)
   }
 } {1 {no query solution}}
-ifcapable stat4||stat3 {
-  # When STAT3 is enabled, the "b NOT NULL" terms get translated
-  # into b>NULL, which can be satified by the index t1b.  It is a very
-  # expensive way to do the query, but it works, and so a solution is possible.
-  do_test where9-6.8.3-stat4 {
-    catchsql {
-      UPDATE t1 INDEXED BY t1b SET a=a+100
-       WHERE (b IS NULL AND c NOT NULL AND d NOT NULL)
-          OR (b NOT NULL AND c IS NULL AND d NOT NULL)
-          OR (b NOT NULL AND c NOT NULL AND d IS NULL)
-    }
-  } {0 {}}
-  do_test where9-6.8.4-stat4 {
-    catchsql {
-      DELETE FROM t1 INDEXED BY t1b
-       WHERE (b IS NULL AND c NOT NULL AND d NOT NULL)
-          OR (b NOT NULL AND c IS NULL AND d NOT NULL)
-          OR (b NOT NULL AND c NOT NULL AND d IS NULL)
-    }
-  } {0 {}}
-} else {
+if {1} {
   do_test where9-6.8.3 {
     catchsql {
       UPDATE t1 INDEXED BY t1b SET a=a+100