]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Experiments in picking better query plans, especially when the usage of one
authordrh <drh@noemail.net>
Sat, 29 Mar 2014 21:16:07 +0000 (21:16 +0000)
committerdrh <drh@noemail.net>
Sat, 29 Mar 2014 21:16:07 +0000 (21:16 +0000)
index is a subset of another.

FossilOrigin-Name: 8f869ca7a6eaa9ca7a08102290e6c606735f9090

manifest
manifest.uuid
src/where.c

index 52d212de1df069ce2e314a6d722ecc49a5d85804..9ef65fa6b92c01b3883bac303c8a7294be84844a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Disable\sthe\swal64k.test\sscript\sfor\snon-unix\ssystems\ssince\sit\sdepends\son\nunix-only\sfeatures.
-D 2014-03-28T14:41:35.536
+C Experiments\sin\spicking\sbetter\squery\splans,\sespecially\swhen\sthe\susage\sof\sone\nindex\sis\sa\ssubset\sof\sanother.
+D 2014-03-29T21:16:07.103
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -291,7 +291,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
 F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
-F src/where.c 7d539cedb1c6a6d6b5d2075b8fea3a48db4838eb
+F src/where.c 26c6f6260b0cc2b0038dcc68ace0d7db20c7dcee
 F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -1159,7 +1159,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P a4e47150f32b3a4120b1f89ccc66d633d829e3bb
-R 578568415288cd31fe0adba6128329da
+P 27deb6e49bcc76714dbdc61b34748603155ac770
+R 1df7985395668b26c614cc4e641f29c8
+T *branch * query-plan-experiments
+T *sym-query-plan-experiments *
+T -sym-trunk *
 U drh
-Z 045e2748905f8bd05ecf1197b97d7f20
+Z 1c5ff3f986da6bbe350c60cf72c963dd
index d9c988d4d57650f6fe9578296b10186c645cfc59..05916c40aa607837461cf3a14a87a35f6932396e 100644 (file)
@@ -1 +1 @@
-27deb6e49bcc76714dbdc61b34748603155ac770
\ No newline at end of file
+8f869ca7a6eaa9ca7a08102290e6c606735f9090
\ No newline at end of file
index 93ee8c59c310f0a441a2068e69cb7fe22701c136..c2b2cf2111b714cf6b20d21f269d2435f47cc540 100644 (file)
@@ -3712,59 +3712,24 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
 }
 
 /*
-** Insert or replace a WhereLoop entry using the template supplied.
+** Search the list of WhereLoops in *ppPrev looking for one that can be
+** supplanted by pTemplate.
 **
-** An existing WhereLoop entry might be overwritten if the new template
-** is better and has fewer dependencies.  Or the template will be ignored
-** and no insert will occur if an existing WhereLoop is faster and has
-** fewer dependencies than the template.  Otherwise a new WhereLoop is
-** added based on the template.
+** Return NULL if the WhereLoop list contains an entry that can supplant
+** pTemplate, in other words if pTemplate does not belong on the list.
 **
-** If pBuilder->pOrSet is not NULL then we only care about only the
-** prerequisites and rRun and nOut costs of the N best loops.  That
-** information is gathered in the pBuilder->pOrSet object.  This special
-** processing mode is used only for OR clause processing.
+** If pX is a WhereLoop that pTemplate can supplant, then return the
+** link that points to pX.
 **
-** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
-** still might overwrite similar loops with the new template if the
-** template is better.  Loops may be overwritten if the following 
-** conditions are met:
-**
-**    (1)  They have the same iTab.
-**    (2)  They have the same iSortIdx.
-**    (3)  The template has same or fewer dependencies than the current loop
-**    (4)  The template has the same or lower cost than the current loop
-**    (5)  The template uses more terms of the same index but has no additional
-**         dependencies          
+** If pTemplate cannot supplant any existing element of the list but needs
+** to be added to the list, then return a pointer to the tail of the list.
 */
-static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
-  WhereLoop **ppPrev, *p, *pNext = 0;
-  WhereInfo *pWInfo = pBuilder->pWInfo;
-  sqlite3 *db = pWInfo->pParse->db;
-
-  /* If pBuilder->pOrSet is defined, then only keep track of the costs
-  ** and prereqs.
-  */
-  if( pBuilder->pOrSet!=0 ){
-#if WHERETRACE_ENABLED
-    u16 n = pBuilder->pOrSet->n;
-    int x =
-#endif
-    whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
-                                    pTemplate->nOut);
-#if WHERETRACE_ENABLED /* 0x8 */
-    if( sqlite3WhereTrace & 0x8 ){
-      sqlite3DebugPrintf(x?"   or-%d:  ":"   or-X:  ", n);
-      whereLoopPrint(pTemplate, pBuilder->pWC);
-    }
-#endif
-    return SQLITE_OK;
-  }
-
-  /* Search for an existing WhereLoop to overwrite, or which takes
-  ** priority over pTemplate.
-  */
-  for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){
+static WhereLoop **whereLoopFindLesser(
+  WhereLoop **ppPrev,
+  const WhereLoop *pTemplate
+){
+  WhereLoop *p;
+  for(p=(*ppPrev); p; ppPrev=&p->pNextLoop, p=*ppPrev){
     if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){
       /* If either the iTab or iSortIdx values for two WhereLoop are different
       ** then those WhereLoops need to be considered separately.  Neither is
@@ -3799,12 +3764,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
       ){
         /* Overwrite an existing WhereLoop with an similar one that uses
         ** more terms of the index */
-        pNext = p->pNextLoop;
         break;
       }else{
-        /* pTemplate is not helpful.
-        ** Return without changing or adding anything */
-        goto whereLoopInsert_noop;
+        /* There is an existing WhereLoop that is better than pTemplate */
+        return 0;
       }
     }
     if( (p->prereq & pTemplate->prereq)==pTemplate->prereq
@@ -3816,10 +3779,79 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
       ** or (4) number of output rows, and is no worse in any of those
       ** categories. */
       assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */
-      pNext = p->pNextLoop;
       break;
     }
   }
+  return ppPrev;
+}
+
+/*
+** Insert or replace a WhereLoop entry using the template supplied.
+**
+** An existing WhereLoop entry might be overwritten if the new template
+** is better and has fewer dependencies.  Or the template will be ignored
+** and no insert will occur if an existing WhereLoop is faster and has
+** fewer dependencies than the template.  Otherwise a new WhereLoop is
+** added based on the template.
+**
+** If pBuilder->pOrSet is not NULL then we care about only the
+** prerequisites and rRun and nOut costs of the N best loops.  That
+** information is gathered in the pBuilder->pOrSet object.  This special
+** processing mode is used only for OR clause processing.
+**
+** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
+** still might overwrite similar loops with the new template if the
+** template is better.  Loops may be overwritten if the following 
+** conditions are met:
+**
+**    (1)  They have the same iTab.
+**    (2)  They have the same iSortIdx.
+**    (3)  The template has same or fewer dependencies than the current loop
+**    (4)  The template has the same or lower cost than the current loop
+**    (5)  The template uses more terms of the same index but has no additional
+**         dependencies          
+*/
+static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
+  WhereLoop **ppPrev, *p;
+  WhereInfo *pWInfo = pBuilder->pWInfo;
+  sqlite3 *db = pWInfo->pParse->db;
+
+  /* If pBuilder->pOrSet is defined, then only keep track of the costs
+  ** and prereqs.
+  */
+  if( pBuilder->pOrSet!=0 ){
+#if WHERETRACE_ENABLED
+    u16 n = pBuilder->pOrSet->n;
+    int x =
+#endif
+    whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
+                                    pTemplate->nOut);
+#if WHERETRACE_ENABLED /* 0x8 */
+    if( sqlite3WhereTrace & 0x8 ){
+      sqlite3DebugPrintf(x?"   or-%d:  ":"   or-X:  ", n);
+      whereLoopPrint(pTemplate, pBuilder->pWC);
+    }
+#endif
+    return SQLITE_OK;
+  }
+
+  /* Look for an existing WhereLoop to replace with pTemplate
+  */
+  ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);
+
+  if( ppPrev==0 ){
+    /* There already exists a WhereLoop on the list that is better
+    ** than pTemplate, so just ignore pTemplate */
+#if WHERETRACE_ENABLED /* 0x8 */
+    if( sqlite3WhereTrace & 0x8 ){
+      sqlite3DebugPrintf("ins-noop: ");
+      whereLoopPrint(pTemplate, pBuilder->pWC);
+    }
+#endif
+    return SQLITE_OK;  
+  }else{
+    p = *ppPrev;
+  }
 
   /* If we reach this point it means that either p[] should be overwritten
   ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
@@ -3836,13 +3868,33 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
   }
 #endif
   if( p==0 ){
-    p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
+    /* Allocate a new WhereLoop to add to the end of the list */
+    *ppPrev = p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
     if( p==0 ) return SQLITE_NOMEM;
     whereLoopInit(p);
+    p->pNextLoop = 0;
+  }else{
+    /* We will be overwriting WhereLoop p[].  But before we do, first
+    ** go through the rest of the list and delete any other entries besides
+    ** p[] that are also supplated by pTemplate */
+    WhereLoop **ppTail = &p->pNextLoop;
+    WhereLoop *pToDel;
+    while( *ppTail ){
+      ppTail = whereLoopFindLesser(ppTail, pTemplate);
+      if( NEVER(ppTail==0) ) break;
+      pToDel = *ppTail;
+      if( pToDel==0 ) break;
+      *ppTail = pToDel->pNextLoop;
+#if WHERETRACE_ENABLED /* 0x8 */
+      if( sqlite3WhereTrace & 0x8 ){
+        sqlite3DebugPrintf("ins-del: ");
+        whereLoopPrint(pToDel, pBuilder->pWC);
+      }
+#endif
+      whereLoopDelete(db, pToDel);
+    }
   }
   whereLoopXfer(db, p, pTemplate);
-  p->pNextLoop = pNext;
-  *ppPrev = p;
   if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
     Index *pIndex = p->u.btree.pIndex;
     if( pIndex && pIndex->tnum==0 ){
@@ -3850,16 +3902,6 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
     }
   }
   return SQLITE_OK;
-
-  /* Jump here if the insert is a no-op */
-whereLoopInsert_noop:
-#if WHERETRACE_ENABLED /* 0x8 */
-  if( sqlite3WhereTrace & 0x8 ){
-    sqlite3DebugPrintf("ins-noop: ");
-    whereLoopPrint(pTemplate, pBuilder->pWC);
-  }
-#endif
-  return SQLITE_OK;  
 }
 
 /*