Am 18.12.2009 um 15:58 schrieb Pavel Ivanov: > As you said because of your LEFT JOIN SQLite (or any other DBMS in its > place) is forced to use t2 as a base table. You have no conditions on > t2, so SQLite will make full scan on it and for each row it will need > to pick up a corresponding rows from t1 which it does using primary > index. > > And FYI, by using condition "where t1.uid = 'x'" you're killing all > purpose of LEFT JOIN - you're forcing for the row in t1 to exist and > thus you can with the same success use INNER JOIN for this query. But > if you do use it I believe SQLite will be smart enough to select rows > from t1 using t1_idx and then for each row pick up corresponding row > from t2 using t2_idx.
Thanks, you're right, of course... sometimes, it's hard to think outside one's box :( And yes - using an INNER JOIN will actually make SQLite use the proper indexes. Thanks a lot! </jum> > > On Fri, Dec 18, 2009 at 3:52 AM, Jens Miltner <j...@mac.com> wrote: >> Hi everybody, >> >> consider the following database schema: >> >> CREATE TABLE t1 ( >> id INTEGER PRIMARY KEY, >> uid, >> x >> ); >> CREATE INDEX t1_idx ON t1(uid); >> CREATE TABLE t2 ( >> id INTEGER PRIMARY KEY, >> t1_id INTEGER, >> y >> ); >> CREATE INDEX t2_idx ON t2(t1_id); >> >> >> Shouldn't the following query attempt to use both indexes, instead of >> not using an index on table t2: >> >> sqlite> EXPLAIN QUERY PLAN SELECT * FROM t2 LEFT JOIN t1 ON >> t1.id=t2.t1_id WHERE t1.uid='x'; >> 0|0|TABLE t2 >> 1|1|TABLE t1 USING PRIMARY KEY >> >> even when explicitely forcing to use t1_idx, no index on t2 will be >> used: >> >> sqlite> EXPLAIN QUERY PLAN SELECT * FROM t2 LEFT JOIN t1 ON >> +t1.id=t2.t1_id WHERE t1.uid='x'; >> 0|0|TABLE t2 >> 1|1|TABLE t1 WITH INDEX t1_idx >> >> >> I would have expected the query optimizer to use t1_idx and t2_idx? >> I understand that using the LEFT JOIN in the way I did above will >> have >> to use t2 as the base table, but shouldn't this also be possible when >> filtering on t1 first (by uid) and then applying the JOIN to records >> from t2 satisfying the JOIN condition? >> >> It definitely would make sense in the case I have in mind where t2 >> contains much, much more records than t1 and only very few of them >> actually satisfy the JOIN condition AND the uid condition... >> I found that I can rewrite the query as >> >> sqlite> EXPLAIN QUERY PLAN SELECT * FROM t2 LEFT JOIN t1 ON >> t1.id=t2.t1_id WHERE t2.t1_id=(SELECT id FROM t1 WHERE uid='x'); >> 0|0|TABLE t2 WITH INDEX t2_idx >> 1|1|TABLE t1 USING PRIMARY KEY >> 0|0|TABLE t1 WITH INDEX t1_idx >> >> but this is somewhat awkward and hard to do in our case, since the >> queries are generated dynamically... >> Wouldn't/Shouldn't the query optimizer be able to do this kind of >> optimization without me explicitely rewriting the query (especially >> when I have run ANALYZE, so the optimizer knows the data >> distribution)? >> >> Don't get me wrong - I'm not trying to complain, I'd just like to >> understand whether there is potential for the query optimizer to >> transparently optimize queries as the above or whether I'm completely >> off with my idea :) >> >> >> Thanks, >> </jum> >> >> _______________________________________________ >> sqlite-users mailing list >> sqlite-users@sqlite.org >> http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users >> > _______________________________________________ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users