When upgrading from 3.7.14.1 to 3.24 I noticed the following problem Given a virtual table like
CREATE VIRTUAL TABLE vt ( key1 INTEGER, key2 INTEGER, key3 INTEGER, attr1 INTEGER,...); whose xBestIndex function simulates (in unsupported syntax) CREATE VIRTUAL INDEX vt_key ON vt (key1, key2, key3); but also handles simple comparisons internally, the query SELECT * FROM vt WHERE key1 = <val1> AND key2 BETWEEN <val2> AND <val3> AND attr1 IN (<list>); SQLite 3.7.14.1 asks for (key1,'='), (key2,'>='), (key2,'<=') and xBestIndex accepts all 3 constraints yielding query plan - materialize IN <list> as anonymous ephemeral table - search vt using index 1 (key1 = ? AND key2 >= ? AND key2 <= ?) - retrieve column attr1 - search anonymous ephemeral table i.e. perform a single partial table scan on vt and check attr1 SQLite3.24 asks for ...,(attr1,'=') and xBestIndex accepts all 4 constraints yielding - materialize IN (<list>) as anonymous ephemeral table - scan anonymous ephemeral table - search vt using index 1 (key1 = ? AND key2 >= ? AND key2 <= ? AND attr1 = ?) i.e. perform a partial table scan of vt FOR EACH attr1, which is slower by the cardinality of the IN list Fortunately, CTEs come to the rescue: WITH attrs (attr1) AS (VALUES <(list)>) SELECT * FROM vt CROSS JOIN attrs a ON (a.attr1 = vt.attr1) WHERE key1 = <val1> AND key2 BETWEEN <val2> AND <val3> This prevents SQLite 3.24 from adding the last constraint, yielding - materialize IN (<(list)>) as epehemeral table attrs - search vt using index 1 (key1 = ? AND key2 >= ? AND key2 <= ?) - retrieve column attr1 - scan ephemeral table attrs The only issue is that the previously generated ephemeral table was implemented as a covering index (allowing the sequence IfNull, Affinity, NotFound) whereas the named ephemeral table is implemented as a table (requiring a full table scan of the ephemeral table, even though at most 1 row can match) Optimisation opportunity: 32 Rewind 1 40 0 00 33 Column 1 0 10 00 r[10]=events.event_type 34 VColumn 0 15 11 00 r[11]=vcolumn(15); atx_txlog.event_type 35 Ne 11 38 10 (BINARY) 53 if r[10]!=r[11] goto 38 36 VColumn 0 6 12 00 r[12]=vcolumn(6); atx_txlog.sync_offset 37 ResultRow 12 1 0 00 output=r[12] 38 Next 1 33 0 01 Could IMHO be rewritten as 32 VColumn 0 15 11 00 r[11]=vcolumn(15); atx_txlog.event_type 33 Rewind 1 40 0 00 34 Column 1 0 10 00 r[10]=events.event_type 35 Ne 11 38 10 (BINARY) 53 if r[10]!=r[11] goto 38 36 VColumn 0 6 12 00 r[12]=vcolumn(6); atx_txlog.sync_offset 37 ResultRow 12 1 0 00 output=r[12] 38 Next 1 33 0 01 ___________________________________________ Gunter Hick | Software Engineer | Scientific Games International GmbH | Klitschgasse 2-4, A-1130 Vienna | FN 157284 a, HG Wien, DVR: 0430013 | (O) +43 1 80100 - 0 May be privileged. May be confidential. Please delete if not the addressee. _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users