On 3 Mar 2015, at 11:10am, Eric Grange <zarglu at gmail.com> wrote:
> With indexes on A & B, the performance of the above is not very good, as
> indexing A1 is not enough, and indexing B1 is not enough either, so no
> query plan is satisfying.
The B1 index isn't going to be used. Here is your query:
select ...some fields of A & B...
from A join B on A.A2 = B.B2
where A.A1 = ?1
order by B.B1
limit 100
An index on A.A1 is good, since it satisfies the "WHERE" clause. So do that as
you did.
Once SQLite has found relevant rows of A it's processing the "JOIN". This
means going through table B.B2 looking for rows which match existing values of
A.A2. You need an index on B.B2. But having done that the "ORDER BY" clause
means it needs to order the resulting rows by B.B1. So one index which allowed
both might provide the best advantage. Try
CREATE INDEX B_2_1 ON B (B2, B1)
then do an ANALYZE, and see if that helps matters. Another approach is to look
at your "ORDER BY" clause and see that what you're doing is based on ordering
by B.B1, sp another way to see your query is
select ...some fields of A & B...
from B join A on A.A2 = B.B2
where A.A1 = ?1
order by B.B1
limit 100
This would be best helped with an index on B.B1 and another on A.A1 and A.A2.
I suggest you do
CREATE INDEX B_1_2 ON B (B1, B2)
CREATE INDEX B_2_1 ON B (B2, B1)
CREATE INDEX A_1_2 ON A (A1, A2)
CREATE INDEX A_2_1 ON A (A2, A1)
then do an ANALYZE, then execute the query as rephrased above. If this turns
out to be faster you can use EXPLAIN QUERY PLAN to find out which indexes
SQLite is doing and delete the unused ones.
Simon.