Without an order by, sqlite can return the rows in any order it pleases. Likely 
whatever consumes the least resources. Although unlikely given your indices, it 
might be possible - for instance if some future micro-optimisation finds that 
it's quicker to read the index in reverse, then sqlite would give things in the 
opposite order. If you leave out a necessary order by you are very much 
exposing yourself to internal changes. So much so that there is a pragma 
reverse_unordered_selects 
(https://www.sqlite.org/pragma.html#pragma_reverse_unordered_selects) you can 
use to specifically find if your app makes invalid assumptions about order.

You might have found a missed optimisation opportunity here (although there's 
always the tradeoff of library size & cycles to optimise vs execution cycles 
saved to consider).

> On 16 Sep 2018, at 6:29 pm, John Found <johnfo...@asm32.info> wrote:
> 
> Is there some relation between the indexes used in the query, the GROUP BY 
> fields used 
> and the order of the result rows, when no "ORDER BY" clause is used?
> 
> I am asking, because I noticed, that on some queries, when I am using "ORDER 
> BY" the query always 
> use temporary b-tree for ordering, but by including the needed fields in the 
> "GROUP BY" clause 
> and removing the ORDER BY clause, the query returns the rows in the proper 
> order without temp b-tree.
> 
> So, is it safe to use this implicit ordering, or this behavior can be changed 
> in the future versions of SQLite?
> 
> Here is an example:
> 
> create table A (
>  id integer primary key autoincrement,
>  o1 integer,
>  o2 integer
> );
> 
> create table B (
>  Aid integer references A(id),
>  data text
> );
> 
> create index idxA on A(o1 desc, o2 desc);
> 
> insert into A(o1, o2) values (1, 100), (2, 50), (3, 200), (5, 300);
> insert into B(Aid, data) values (1, "b"), (1, "a"), (2, "c"), (2, "d"), (2, 
> "e"), (3, "f"), (3, "g");
> 
> -- Always uses temp b-tree for order by
> select 
>  group_concat(B.data), o1, o2
> from 
>  A
> left join 
>  B on A.id = B.Aid
> group by 
>  A.id
> order by 
>  A.o1 desc, A.o2 desc;
> 
> explain query plan:
> id    parent    notused    detail
> 8    0    0    SCAN TABLE A
> 19    0    0    SEARCH TABLE B USING AUTOMATIC COVERING INDEX (Aid=?)
> 58    0    0    USE TEMP B-TREE FOR ORDER BY
> 
> 
> -- This one returns the rows in the needed order without ORDER BY
> select 
>  group_concat(B.data), o1, o2
> from 
>  A indexed by idxA
> left join B on A.id = B.Aid
> group by A.id, A.o1, A.o2;
> 
> explain query plan:
> id    parent    notused    detail
> 7    0    0    SCAN TABLE A USING COVERING INDEX idxA
> 18    0    0    SEARCH TABLE B USING AUTOMATIC COVERING INDEX (Aid=?)
> 
> 
> -- But if I add ORDER BY it still begins to use temp b-tree 
> -- regardless that it does not change the order.
> select 
>  group_concat(B.data), o1, o2
> from 
>  A indexed by idxA
> left join B on A.id = B.Aid
> group by A.id, A.o1, A.o2
> order by A.o1 desc, A.o2 desc;
> 
> explain query plan:
> 8    0    0    SCAN TABLE A
> 19    0    0    SEARCH TABLE B USING AUTOMATIC COVERING INDEX (Aid=?)
> 60    0    0    USE TEMP B-TREE FOR ORDER BY
> 
> 
> All the above queries, returns the same result rows in the same order:
> 
> group_concat(B.data)  o1   o2
> NULL                   5   300
> f,g                    3   200
> c,d,e                  2   50
> a,b                    1   100
> 
> 
> 
>        
> -- 
> John Found <johnfo...@asm32.info>
> _______________________________________________
> sqlite-users mailing list
> sqlite-users@mailinglists.sqlite.org
> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to