Hi List,
I was looking at the query plan of a rather simple query, but I don't
understand why sqlite would choose this query plan.
For the following example:
create table aaa(id INTEGER, name_id INTEGER, type CHAR);
create table bbb(name_id INTEGER, name CHAR);
create index ix_aaa ON aaa(id);
create index ix_bbb ON bbb(name_id);
.explain ON
explain query plan
SELECT aaa1.name_id,
bbb1.name
FROM aaa aaa1,
aaa aaa2 ON aaa1.id = aaa2.id,
bbb bbb1 ON bbb1.name_id = aaa1.name_id
WHERE aaa1.type = 'A'
AND aaa2.type <> 'A';
=========== output ==============
SELECT item[0] = {0:1}
item[1] = {2:1}
FROM {0,*} = aaa (AS aaa1)
{1,*} = aaa (AS aaa2)
{2,*} = bbb (AS bbb1)
WHERE AND(AND(AND(EQ({0:2},'A'),NE({1:2},'A')),EQ({0:0},{1:0})),EQ({2:0},{0:1}))
END
sele order from deta
---- ------------- ---- ----
0 0 0 SEARCH TABLE aaa AS aaa1 USING AUTOMATIC COVERING
INDEX (type=?)
0 1 1 SEARCH TABLE aaa AS aaa2 USING INDEX ix_aaa (id=?)
0 2 2 SEARCH TABLE bbb AS bbb1 USING INDEX ix_bbb
(name_id=?)
Sqlite decides to create an AUTOMATIC INDEX (time complexity O(n log n)) which
it then uses to iterate table aaa1. This index is not re-used for anything else
(it can't be re-used since 'type' is not used anywhere else) so only the
traversal of table aaa1 benefits from this index. However, I think, a full
table scan of aaa1 (time complexity O(n)) would always be faster, since for
creating the index it has to read that entire table anyway.
I was surprised that sqlite came up with the inferior query plan.
What makes sqlite think that creating + using an automatic index (for the outer
loop) makes the query faster the a full scan + filtering records? Is the
estimation of the costs for some action very bad for this query? Can I somehow
show the costs of a query plans (or of the rejected query plans)?
I'm using sqlite version 3.8.4.3
Note: After an "analyze aaa" (on a decently populated table) sqlite chooses the
full table scan instead of creating an automatic index (but our application
never uses 'analyze' to avoid that other (bad performing) query plans are used
during operation than during testing).
Note 2: Adding "NOT INDEXED" to aa1 gives the desired query plan, but of course
I prefer that sqlite choses the right query plan.
Regards,
Rob Golsteijn
_______________________________________________
sqlite-users mailing list
[email protected]
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users