]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make more aggressive use of transitivity in optimizing queries. Add a test
authordrh <drh@noemail.net>
Thu, 17 Jan 2013 15:05:17 +0000 (15:05 +0000)
committerdrh <drh@noemail.net>
Thu, 17 Jan 2013 15:05:17 +0000 (15:05 +0000)
case.

FossilOrigin-Name: d96762841a461e192fb2f317d684d000376350dd

manifest
manifest.uuid
src/where.c
test/autoindex1.test

index bf95c9a433d6e5c73e2bb3866c46fa361e152527..fb4188f095a06c6960730bfec5c8542261ca5477 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Improved\scomments\sexplaining\sthe\soperation\sof\sthe\sfindTerm()\sutility\sroutine\nin\swhere.c.\s\sIncrease\sthe\smaximum\snumber\sof\slevels\sof\stransitivity\sfrom\s4\nto\s11.
-D 2013-01-17T00:08:42.232
+C Make\smore\saggressive\suse\sof\stransitivity\sin\soptimizing\squeries.\s\sAdd\sa\stest\ncase.
+D 2013-01-17T15:05:17.153
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in a48faa9e7dd7d556d84f5456eabe5825dd8a6282
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -252,7 +252,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
 F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2
 F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
 F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
-F src/where.c 24d74ec54a71e01e0672e0838f7dd5757fb6324d
+F src/where.c 701c32fecbcf44d749a8fdacb887ffdcec21a3e5
 F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -285,7 +285,7 @@ F test/auth.test 304e82f31592820d3bde26ab6b75deaa123e1a6f
 F test/auth2.test a2a371aa6df15f8b0c8109b33d3d7f0f73e4c9aa
 F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
 F test/autoinc.test bd30d372d00045252f6c2e41b5f41455e1975acf
-F test/autoindex1.test 058d0b331ae6840a61bbee910d8cbae27bfd5991
+F test/autoindex1.test f88146c4c889ea0afbb620e49d83b5fbf5ee4d06
 F test/autovacuum.test 9f22a7733f39c56ef6a5665d10145ac25d8cb574
 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
 F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
@@ -1033,7 +1033,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P 13171eb5dc19733276fbfd5515d75b70a9f5f5d7
-R 47b8015795abaf8b9e9739389b1b5d3d
+P fe152f8b048c9a18f99fa6096ff0e68dd630c318
+R f7b812e14ccd12b59aae7b48f0da1945
 U drh
-Z c72ed7f67d993d6d7e18306e36936017
+Z eaf427dd060ebdbe2c55df9e5c68a5b1
index 725783fc543713eb078969f0b104345b1662b771..c667be658bfc33bef6376b8c1d0a5ca811ecc147 100644 (file)
@@ -1 +1 @@
-fe152f8b048c9a18f99fa6096ff0e68dd630c318
\ No newline at end of file
+d96762841a461e192fb2f317d684d000376350dd
\ No newline at end of file
index 6635d8eaee9bc6a3bba1f6329dbdbacc4edee3be..ca59370352be7dd0540d920c7d546f0cfd0e5787 100644 (file)
@@ -663,6 +663,7 @@ static WhereTerm *findTerm(
   int j, k;                    /* Loop counters */
   Expr *pX;                /* Pointer to an expression */
   Parse *pParse;           /* Parsing context */
+  int iOrigCol = iColumn;  /* Original value of iColumn */
   int nEquiv = 2;          /* Number of entires in aEquiv[] */
   int iEquiv = 2;          /* Number of entries of aEquiv[] processed so far */
   int aEquiv[22];          /* iCur,iColumn and up to 10 other equivalents */
@@ -675,16 +676,17 @@ static WhereTerm *findTerm(
       for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
         if( pTerm->leftCursor==iCur
           && pTerm->u.leftColumn==iColumn
-          && (pTerm->eOperator & op & WO_ALL)!=0
         ){
-          if( (pTerm->prereqRight & notReady)==0 ){
-            if( iColumn>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
+          if( (pTerm->prereqRight & notReady)==0
+           && (pTerm->eOperator & op & WO_ALL)!=0
+          ){
+            if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
               CollSeq *pColl;
               char idxaff;
       
               pX = pTerm->pExpr;
               pParse = pWC->pParse;
-              idxaff = pIdx->pTable->aCol[iColumn].affinity;
+              idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
               if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
       
               /* Figure out the collation sequence required from an index for
@@ -695,7 +697,7 @@ static WhereTerm *findTerm(
               pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
               if( pColl==0 ) pColl = pParse->db->pDfltColl;
       
-              for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
+              for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
                 if( NEVER(j>=pIdx->nColumn) ) return 0;
               }
               if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
@@ -703,8 +705,7 @@ static WhereTerm *findTerm(
             pResult = pTerm;
             if( pTerm->prereqRight==0 ) goto findTerm_success;
           }
-          if( (op&WO_EQ)!=0
-           && (pTerm->eOperator & WO_EQUIV)!=0
+          if( (pTerm->eOperator & WO_EQUIV)!=0
            && nEquiv<ArraySize(aEquiv)
           ){
             pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
@@ -724,7 +725,6 @@ static WhereTerm *findTerm(
     if( iEquiv>=nEquiv ) break;
     iCur = aEquiv[iEquiv++];
     iColumn = aEquiv[iEquiv++];
-    op &= WO_EQ;
   }
 findTerm_success:
   return pResult;
@@ -1005,7 +1005,6 @@ static void exprAnalyzeOrTerm(
   for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
     if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
       WhereAndInfo *pAndInfo;
-      assert( pOrTerm->eOperator==0 );
       assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
       chngToIN = 0;
       pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
@@ -1291,13 +1290,14 @@ static void exprAnalyze(
   pTerm->leftCursor = -1;
   pTerm->iParent = -1;
   pTerm->eOperator = 0;
-  if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
+  if( allowedOp(op) ){
     Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
     Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
+    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
     if( pLeft->op==TK_COLUMN ){
       pTerm->leftCursor = pLeft->iTable;
       pTerm->u.leftColumn = pLeft->iColumn;
-      pTerm->eOperator = operatorMask(op);
+      pTerm->eOperator = operatorMask(op) & opMask;
     }
     if( pRight && pRight->op==TK_COLUMN ){
       WhereTerm *pNew;
@@ -1332,7 +1332,7 @@ static void exprAnalyze(
       testcase( (prereqLeft | extraRight) != prereqLeft );
       pNew->prereqRight = prereqLeft | extraRight;
       pNew->prereqAll = prereqAll;
-      pNew->eOperator = operatorMask(pDup->op) + eExtraOp;
+      pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
     }
   }
 
index 6c8d54d12523de484ffce3b24bbbd741c0c0dae4..54ff82a2b08c6570c9652027e1863699aa10d18c 100644 (file)
@@ -257,5 +257,129 @@ do_execsql_test autoindex1-700 {
   0 0 0 {USE TEMP B-TREE FOR ORDER BY}
 }
 
+# The following checks a performance issue reported on the sqlite-dev
+# mailing list on 2013-01-10
+#
+do_execsql_test autoindex1-800 {
+  CREATE TABLE accounts(
+    _id INTEGER PRIMARY KEY AUTOINCREMENT,
+    account_name TEXT,
+    account_type TEXT,
+    data_set TEXT
+  );
+  CREATE TABLE data(
+    _id INTEGER PRIMARY KEY AUTOINCREMENT,
+    package_id INTEGER REFERENCES package(_id),
+    mimetype_id INTEGER REFERENCES mimetype(_id) NOT NULL,
+    raw_contact_id INTEGER REFERENCES raw_contacts(_id) NOT NULL,
+    is_read_only INTEGER NOT NULL DEFAULT 0,
+    is_primary INTEGER NOT NULL DEFAULT 0,
+    is_super_primary INTEGER NOT NULL DEFAULT 0,
+    data_version INTEGER NOT NULL DEFAULT 0,
+    data1 TEXT,
+    data2 TEXT,
+    data3 TEXT,
+    data4 TEXT,
+    data5 TEXT,
+    data6 TEXT,
+    data7 TEXT,
+    data8 TEXT,
+    data9 TEXT,
+    data10 TEXT,
+    data11 TEXT,
+    data12 TEXT,
+    data13 TEXT,
+    data14 TEXT,
+    data15 TEXT,
+    data_sync1 TEXT,
+    data_sync2 TEXT,
+    data_sync3 TEXT,
+    data_sync4 TEXT 
+  );
+  CREATE TABLE mimetypes(
+    _id INTEGER PRIMARY KEY AUTOINCREMENT,
+    mimetype TEXT NOT NULL
+  );
+  CREATE TABLE raw_contacts(
+    _id INTEGER PRIMARY KEY AUTOINCREMENT,
+    account_id INTEGER REFERENCES accounts(_id),
+    sourceid TEXT,
+    raw_contact_is_read_only INTEGER NOT NULL DEFAULT 0,
+    version INTEGER NOT NULL DEFAULT 1,
+    dirty INTEGER NOT NULL DEFAULT 0,
+    deleted INTEGER NOT NULL DEFAULT 0,
+    contact_id INTEGER REFERENCES contacts(_id),
+    aggregation_mode INTEGER NOT NULL DEFAULT 0,
+    aggregation_needed INTEGER NOT NULL DEFAULT 1,
+    custom_ringtone TEXT,
+    send_to_voicemail INTEGER NOT NULL DEFAULT 0,
+    times_contacted INTEGER NOT NULL DEFAULT 0,
+    last_time_contacted INTEGER,
+    starred INTEGER NOT NULL DEFAULT 0,
+    display_name TEXT,
+    display_name_alt TEXT,
+    display_name_source INTEGER NOT NULL DEFAULT 0,
+    phonetic_name TEXT,
+    phonetic_name_style TEXT,
+    sort_key TEXT,
+    sort_key_alt TEXT,
+    name_verified INTEGER NOT NULL DEFAULT 0,
+    sync1 TEXT,
+    sync2 TEXT,
+    sync3 TEXT,
+    sync4 TEXT,
+    sync_uid TEXT,
+    sync_version INTEGER NOT NULL DEFAULT 1,
+    has_calendar_event INTEGER NOT NULL DEFAULT 0,
+    modified_time INTEGER,
+    is_restricted INTEGER DEFAULT 0,
+    yp_source TEXT,
+    method_selected INTEGER DEFAULT 0,
+    custom_vibration_type INTEGER DEFAULT 0,
+    custom_ringtone_path TEXT,
+    message_notification TEXT,
+    message_notification_path TEXT
+  );
+  CREATE INDEX data_mimetype_data1_index ON data (mimetype_id,data1);
+  CREATE INDEX data_raw_contact_id ON data (raw_contact_id);
+  CREATE UNIQUE INDEX mime_type ON mimetypes (mimetype);
+  CREATE INDEX raw_contact_sort_key1_index ON raw_contacts (sort_key);
+  CREATE INDEX raw_contact_sort_key2_index ON raw_contacts (sort_key_alt);
+  CREATE INDEX raw_contacts_contact_id_index ON raw_contacts (contact_id);
+  CREATE INDEX raw_contacts_source_id_account_id_index
+      ON raw_contacts (sourceid, account_id);
+  ANALYZE sqlite_master;
+  INSERT INTO sqlite_stat1
+     VALUES('raw_contacts','raw_contact_sort_key2_index','1600 4');
+  INSERT INTO sqlite_stat1
+     VALUES('raw_contacts','raw_contact_sort_key1_index','1600 4');
+  INSERT INTO sqlite_stat1
+     VALUES('raw_contacts','raw_contacts_source_id_account_id_index',
+            '1600 1600 1600');
+  INSERT INTO sqlite_stat1
+     VALUES('raw_contacts','raw_contacts_contact_id_index','1600 1');
+  INSERT INTO sqlite_stat1 VALUES('mimetypes','mime_type','12 1');
+  INSERT INTO sqlite_stat1
+     VALUES('data','data_mimetype_data1_index','9819 2455 3');
+  INSERT INTO sqlite_stat1 VALUES('data','data_raw_contact_id','9819 7');
+  INSERT INTO sqlite_stat1 VALUES('accounts',NULL,'1');
+  DROP TABLE IF EXISTS sqlite_stat3;
+  ANALYZE sqlite_master;
+  
+  EXPLAIN QUERY PLAN
+  SELECT * FROM 
+        data JOIN mimetypes ON (data.mimetype_id=mimetypes._id) 
+             JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id) 
+             JOIN accounts ON (raw_contacts.account_id=accounts._id)
+   WHERE mimetype_id=10 AND data14 IS NOT NULL;
+} {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
+do_execsql_test autoindex1-801 {
+  EXPLAIN QUERY PLAN
+  SELECT * FROM 
+        data JOIN mimetypes ON (data.mimetype_id=mimetypes._id) 
+             JOIN raw_contacts ON (data.raw_contact_id=raw_contacts._id) 
+             JOIN accounts ON (raw_contacts.account_id=accounts._id)
+   WHERE mimetypes._id=10 AND data14 IS NOT NULL;
+} {/SEARCH TABLE data .*SEARCH TABLE raw_contacts/}
 
 finish_test