]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Use the estimated number of rows computed for subqueries in the cost
authordrh <drh@noemail.net>
Tue, 16 Nov 2010 02:49:15 +0000 (02:49 +0000)
committerdrh <drh@noemail.net>
Tue, 16 Nov 2010 02:49:15 +0000 (02:49 +0000)
computations for outer queries.

FossilOrigin-Name: 56bbc539246a6dc9f1ae1edb898db7a4f6f6d322

manifest
manifest.uuid
src/select.c
src/sqliteInt.h
src/where.c
test/autoindex1.test
test/eqp.test

index 6afe3705c51e7a85959b695cc713d3bb34b6e0fd..d06d475d13a5945fa99c86f7dad7269b34c54b3f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-C Change\sthe\sEQP\soutput\sfor\sthe\smin/max\soptimization\sfrom\s"SCAN"\sto\s"SEARCH".\nOther\schanges\sin\swhere.c\sin\ssupport\sof\sfull\sbranch\scoverage\stesting.
-D 2010-11-15T21:50:20
+C Use\sthe\sestimated\snumber\sof\srows\scomputed\sfor\ssubqueries\sin\sthe\scost\ncomputations\sfor\souter\squeries.
+D 2010-11-16T02:49:16
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in e7a59672eaeb04408d1fa8501618d7501a3c5e39
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -177,11 +177,11 @@ F src/printf.c 8ae5082dd38a1b5456030c3755ec3a392cd51506
 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
 F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
-F src/select.c a88ad1cb4af99e47548760d4dd400d2405baff3c
+F src/select.c 550d67688f5e8bc8022faf6d014838afba1415af
 F src/shell.c 8517fc1f9c59ae4007e6cc8b9af91ab231ea2056
 F src/sqlite.h.in f47e09412fc9a129f759fa4d96ef21f4b3d529eb
 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
-F src/sqliteInt.h 8648d013cea93d204faf0959743c47bacd65a85d
+F src/sqliteInt.h dd28f6138c74cf4833e032a989b6ff7885798cf6
 F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
 F src/status.c 496913d4e8441195f6f2a75b1c95993a45b9b30b
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -242,7 +242,7 @@ F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
 F src/wal.c f26b8d297bd11cb792e609917f9d4c6718ac8e0e
 F src/wal.h c1aac6593a0b02b15dc625987e619edeab39292e
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c 6ba0540b6f0239351f2e29b66f1565fe18ef53fe
+F src/where.c d5cc65f51661a038a2c6a663a945d5cf4c277b81
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
 F test/all.test 6745008c144bd2956d58864d21f7b304689c1cce
@@ -267,7 +267,7 @@ F test/auth.test 26cc6f219580191539bf335abe03e55e49310846
 F test/auth2.test 270baddc8b9c273682760cffba6739d907bd2882
 F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
 F test/autoinc.test 85ef3180a737e6580086a018c09c6f1a52759b46
-F test/autoindex1.test 67e2de552a458db13a2eab4fefb291b84f87db5c
+F test/autoindex1.test 860fc83f4fefb0c68ad062afc3ff43faa1534fc4
 F test/autovacuum.test bb7c0885e6f8f1d633045de48f2b66082162766d
 F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6
 F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
@@ -368,7 +368,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
 F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
 F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
 F test/enc4.test 4b575ef09e0eff896e73bd24076f96c2aa6a42de
-F test/eqp.test 7cc9b11f92398843928c2c63525192d4dfdf8df6
+F test/eqp.test 69670e7919030f21de29fb99bf1d68f97aedcbdb
 F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
 F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
 F test/exclusive2.test 76e63c05349cb70d09d60b99d2ae625525ff5155
@@ -889,14 +889,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 136c2ac24ee1663bc0904bce1a619ecef3d11c1c
-R 5f0193dbeb0cbc5cfdd968905645aae6
+P d52b593978aa1776af7aeb957c4f8df0c5cb7e43
+R d49dbce342d6074d2c08ca15a1061dc2
 U drh
-Z 99e502199a00f309bbcf4dd70b11c16e
+Z 1d0a2a683be8d99ef69f89af3e0fc4c3
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.6 (GNU/Linux)
 
-iD8DBQFM4asfoxKgR168RlERAr0gAJ9X2nb2tbe+17ybbefiHGEsu/utZgCfQE+r
-khXtw5KolxWbb2vTQFeG+m0=
-=SW32
+iD8DBQFM4fEvoxKgR168RlERAtLBAJ0duCZxNY8VlhlVLo/NezKrqI5noACdE3GU
+LDKZgeEbRVz6H1/mucVVNUQ=
+=B2su
 -----END PGP SIGNATURE-----
index 1e03318a094e602e56321bb94d6849324d0dd601..5f256ca04e5f27f262746845e88b0b9b55f8cf8a 100644 (file)
@@ -1 +1 @@
-d52b593978aa1776af7aeb957c4f8df0c5cb7e43
\ No newline at end of file
+56bbc539246a6dc9f1ae1edb898db7a4f6f6d322
\ No newline at end of file
index 0f83bbb36f9cefee7e5e7f08be79dc5908d3d6c5..5c5b61589967cb3a70716395b531bdf09e10f552 100644 (file)
@@ -1433,6 +1433,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
       VdbeComment((v, "LIMIT counter"));
       if( n==0 ){
         sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
+      }else{
+        if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
       }
     }else{
       sqlite3ExprCode(pParse, p->pLimit, iLimit);
@@ -1594,6 +1596,7 @@ static int multiSelect(
   switch( p->op ){
     case TK_ALL: {
       int addr = 0;
+      int nLimit;
       assert( !pPrior->pLimit );
       pPrior->pLimit = p->pLimit;
       pPrior->pOffset = p->pOffset;
@@ -1616,6 +1619,13 @@ static int multiSelect(
       testcase( rc!=SQLITE_OK );
       pDelete = p->pPrior;
       p->pPrior = pPrior;
+      p->nSelectRow += pPrior->nSelectRow;
+      if( pPrior->pLimit
+       && sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
+       && p->nSelectRow > (double)nLimit 
+      ){
+        p->nSelectRow = (double)nLimit;
+      }
       if( addr ){
         sqlite3VdbeJumpHere(v, addr);
       }
@@ -1688,6 +1698,7 @@ static int multiSelect(
       pDelete = p->pPrior;
       p->pPrior = pPrior;
       p->pOrderBy = 0;
+      if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
       sqlite3ExprDelete(db, p->pLimit);
       p->pLimit = pLimit;
       p->pOffset = pOffset;
@@ -1767,6 +1778,7 @@ static int multiSelect(
       testcase( rc!=SQLITE_OK );
       pDelete = p->pPrior;
       p->pPrior = pPrior;
+      if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
       sqlite3ExprDelete(db, p->pLimit);
       p->pLimit = pLimit;
       p->pOffset = pOffset;
@@ -2353,6 +2365,7 @@ static int multiSelectOrderBy(
     sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
     sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
     sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
+    p->nSelectRow += pPrior->nSelectRow;
   }
 
   /* Generate a subroutine to run when the results from select B
@@ -2360,6 +2373,7 @@ static int multiSelectOrderBy(
   */
   if( op==TK_INTERSECT ){
     addrEofB = addrEofA;
+    if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
   }else{  
     VdbeNoopComment((v, "eof-B subroutine"));
     addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
@@ -3754,6 +3768,7 @@ int sqlite3Select(
       explainSetInteger(pItem->iSelectId, pParse->iNextSelectId);
       sqlite3Select(pParse, pSub, &dest);
       pItem->isPopulated = 1;
+      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
     }
     if( /*pParse->nErr ||*/ db->mallocFailed ){
       goto select_end;
@@ -3846,6 +3861,7 @@ int sqlite3Select(
   /* Set the limiter.
   */
   iEnd = sqlite3VdbeMakeLabel(v);
+  p->nSelectRow = (double)LARGEST_INT64;
   computeLimitRegisters(pParse, p, iEnd);
 
   /* Open a virtual index to use for the distinct set.
@@ -3869,6 +3885,7 @@ int sqlite3Select(
     */
     pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, 0);
     if( pWInfo==0 ) goto select_end;
+    if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
 
     /* If sorting index that was created by a prior OP_OpenEphemeral 
     ** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -3913,6 +3930,9 @@ int sqlite3Select(
       for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
         pItem->iAlias = 0;
       }
+      if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
+    }else{
+      p->nSelectRow = (double)1;
     }
 
  
index b9eb650d829844898eecbe3bb9dd855f6f875148..c02a0e4487ddd0107401da92024470467c5596a7 100644 (file)
@@ -1947,6 +1947,7 @@ struct WhereInfo {
   int nLevel;                    /* Number of nested loop */
   struct WhereClause *pWC;       /* Decomposition of the WHERE clause */
   double savedNQueryLoop;        /* pParse->nQueryLoop outside the WHERE loop */
+  double nRowOut;                /* Estimated number of output rows */
   WhereLevel a[1];               /* Information about each nest loop in WHERE */
 };
 
@@ -2022,6 +2023,7 @@ struct Select {
   Expr *pOffset;         /* OFFSET expression. NULL means not used. */
   int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
   int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
+  double nSelectRow;     /* Estimated number of result rows */
 };
 
 /*
index 1d6641ee8b1eadb3e3313813d15ef012285ba059..751c7a99c28237ce1306c5256aea68abd973def0 100644 (file)
@@ -4423,6 +4423,7 @@ WhereInfo *sqlite3WhereBegin(
   */
   sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
   notReady = ~(Bitmask)0;
+  pWInfo->nRowOut = (double)1;
   for(i=0, pLevel=pWInfo->a; i<nTabList; i++, pLevel++){
     Table *pTab;     /* Table to open */
     int iDb;         /* Index of database containing table/index */
@@ -4430,6 +4431,7 @@ WhereInfo *sqlite3WhereBegin(
     pTabItem = &pTabList->a[pLevel->iFrom];
     pTab = pTabItem->pTab;
     pLevel->iTabCur = pTabItem->iCursor;
+    pWInfo->nRowOut *= pLevel->plan.nRow;
     iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
     if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
       /* Do nothing */
index 6552fe8b3bcc5ced93c1ccbf8df0c62b4fe7262c..bc628dc256c5b47548432df8d47288a504fe81c6 100644 (file)
@@ -245,7 +245,7 @@ do_execsql_test autoindex1-600 {
   1 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2} 
   2 0 0 {SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?) (~1 rows)} 
   0 0 0 {SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index (~1000000 rows)} 
-  0 1 1 {SEARCH SUBQUERY 1 AS y USING AUTOMATIC COVERING INDEX (sheep_no=?) (~7 rows)}
+  0 1 1 {SEARCH SUBQUERY 1 AS y USING AUTOMATIC COVERING INDEX (sheep_no=?) (~8 rows)}
 }
 
 finish_test
index 1758f9c6a65a2f24f4a73ab0e3c7c428f1d57d82..cd08b8ff16834b8eccc7f942f4492c64b9a21fc0 100644 (file)
@@ -71,6 +71,45 @@ do_eqp_test 1.6 {
   0 0 0 {USE TEMP B-TREE FOR DISTINCT}
 }
 
+do_eqp_test 1.7 {
+  SELECT * FROM t3 JOIN (SELECT 1)
+} {
+  0 0 1 {SCAN SUBQUERY 1 (~1 rows)}
+  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
+}
+do_eqp_test 1.8 {
+  SELECT * FROM t3 JOIN (SELECT 1 UNION SELECT 2)
+} {
+  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (UNION)}
+  0 0 1 {SCAN SUBQUERY 1 (~2 rows)}
+  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
+}
+do_eqp_test 1.9 {
+  SELECT * FROM t3 JOIN (SELECT 1 EXCEPT SELECT a FROM t3 LIMIT 17)
+} {
+  3 0 0 {SCAN TABLE t3 (~1000000 rows)}
+  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (EXCEPT)}
+  0 0 1 {SCAN SUBQUERY 1 (~17 rows)}
+  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
+}
+do_eqp_test 1.10 {
+  SELECT * FROM t3 JOIN (SELECT 1 INTERSECT SELECT a FROM t3 LIMIT 17)
+} {
+  3 0 0 {SCAN TABLE t3 (~1000000 rows)}
+  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 USING TEMP B-TREE (INTERSECT)}
+  0 0 1 {SCAN SUBQUERY 1 (~1 rows)}
+  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
+}
+
+do_eqp_test 1.11 {
+  SELECT * FROM t3 JOIN (SELECT 1 UNION ALL SELECT a FROM t3 LIMIT 17)
+} {
+  3 0 0 {SCAN TABLE t3 (~1000000 rows)}
+  1 0 0 {COMPOUND SUBQUERIES 2 AND 3 (UNION ALL)}
+  0 0 1 {SCAN SUBQUERY 1 (~17 rows)}
+  0 1 0 {SCAN TABLE t3 (~1000000 rows)}
+}
+
 #-------------------------------------------------------------------------
 # Test cases eqp-2.* - tests for single select statements.
 #
@@ -167,7 +206,7 @@ det 3.2.1 {
 } {
   1 0 0 {SCAN TABLE t1 (~1000000 rows)} 
   1 0 0 {USE TEMP B-TREE FOR ORDER BY} 
-  0 0 0 {SCAN SUBQUERY 1 (~1000000 rows)} 
+  0 0 0 {SCAN SUBQUERY 1 (~10 rows)} 
   0 0 0 {USE TEMP B-TREE FOR ORDER BY}
 }
 det 3.2.2 {
@@ -179,8 +218,8 @@ det 3.2.2 {
   1 0 0 {SCAN TABLE t1 (~1000000 rows)} 
   1 0 0 {USE TEMP B-TREE FOR ORDER BY} 
   2 0 0 {SCAN TABLE t2 USING INDEX t2i1 (~1000000 rows)} 
-  0 0 0 {SCAN SUBQUERY 1 AS x1 (~1000000 rows)} 
-  0 1 1 {SCAN SUBQUERY 2 AS x2 (~1000000 rows)} 
+  0 0 0 {SCAN SUBQUERY 1 AS x1 (~10 rows)} 
+  0 1 1 {SCAN SUBQUERY 2 AS x2 (~10 rows)} 
   0 0 0 {USE TEMP B-TREE FOR ORDER BY}
 }
 
@@ -416,7 +455,7 @@ det 5.10 {
   SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x
 } {
   1 0 0 {SCAN TABLE t1 USING COVERING INDEX i2 (~1000000 rows)}
-  0 0 0 {SCAN SUBQUERY 1 (~1000000 rows)}
+  0 0 0 {SCAN SUBQUERY 1 (~100 rows)}
   0 0 0 {USE TEMP B-TREE FOR GROUP BY}
 }