Skip to content
Advertisement

SQLite: optimize query with union

This is my table definition:

create table User (
    userUuid text not null primary key,
    username text not null,
    thisUserBlockedCurrentUser int not null,
    currentUserBlockedThisUserTsCreated int not null,
    searchScreenScore int,
    recentSearchedTsCreated int,
    friends int not null
);

create index User_X on User(thisUserBlockedCurrentUser, friends);

And this is my query + plan:

explain query plan
select *
from (select User.*
      from User
      where friends = 1
        and User.currentUserBlockedThisUserTsCreated is null
        and User.thisUserBlockedCurrentUser = 0
        and User.username != ''
      union
      select User.*
      from User
      where recentSearchedTsCreated is not null
        and User.currentUserBlockedThisUserTsCreated is null
        and User.thisUserBlockedCurrentUser = 0
        and User.username != '')
order by case when friends = 1 then -2 when recentSearchedTsCreated is not null then -1 else searchScreenScore end,
         username;

CO-ROUTINE (subquery-2)
COMPOUND QUERY
LEFT-MOST SUBQUERY
SEARCH User USING INDEX User_X (thisUserBlockedCurrentUser=? AND friends=?)
UNION USING TEMP B-TREE
SEARCH User USING INDEX User_X (thisUserBlockedCurrentUser=?)
SCAN (subquery-2)
USE TEMP B-TREE FOR ORDER BY

So the index is used, but there is still a scan and a b-tree involved in the order by. I tried getting rid of them by adding more indexes, but I don’t get it working.

Any ideas of an index which gets rid of the scan?

Advertisement

Answer

Your query can be simplified to:

SELECT *
FROM User
WHERE (friends = 1 OR recentSearchedTsCreated IS NOT NULL) 
  AND currentUserBlockedThisUserTsCreated IS NULL 
  AND thisUserBlockedCurrentUser = 0 
  AND username <> ''
ORDER BY CASE 
           WHEN friends = 1 THEN -2 
           WHEN recentSearchedTsCreated IS NOT NULL THEN -1 
           ELSE searchScreenScore 
         END,
         username;

and the query plan will be:

SEARCH User USING INDEX User_X (thisUserBlockedCurrentUser=?)
USE TEMP B-TREE FOR ORDER BY

I don’t see how you can get better than B-TREE in the ORDER BY clause since you are using a custom expression to sort by.

See the demo.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement