I’ve been looking for ages about how to do a query like this but use an index.
SELECT * FROM aliens_tmp
WHERE creator != 'a'
AND COUNTRY = 'UK'
ORDER BY id DESC LIMIT 0, 10
Whatever index I create will not get a hit because of the != clashing with the inclusive nature of indexes.
So I thought about doing a minus where I do something like
SELECT * FROM aliens_tmp
WHERE COUNTRY = 'UK
MINUS
SELECT * FROM aliens_tmp
WHERE CREATOR = 'a'
ORDER BY id DESC LIMIT 0, 10
…but MINUS doesn’t exist. So I looked and figured I could use the old trick mentioned on http://www.bitbybit.dk/carsten/blog/?p=71 which briefly is
SELECT DISTINCT a.member_id, a.name
FROM a LEFT JOIN b USING (member_id, name)
WHERE b.member_id IS NULL
but that doesn’t help me with the original goal of doing a MINUS whilst maintaining the use of an index as any join to my own table still has to exclude my creator which causes the miss because of the exclude Any ideas?
If most of your table consists of rows with
creator != 'a'then using index will not give you any advantage. However if you have mostly rows withcreator='a'then you can consider assigning such values to creator (or using enum) that if you order by creator ‘a’ would go first. Instead of checking forcreator != 'a'you could then usecreator > 'a'condition, which is perfectly fine for using btree indexes.UPDATE after more info about creator:
So your
creator != 'a'condition has extremely low selectivity and trying to use index on creator is pointless. You are limiting your results and ordering by id desc, so the key on country should be used to return as few rows as possible by simply checking every single row starting from highest id whether it satisfies where conditions until there are enough for your limit. If you see key: country and number of rows close to 10 in yourexplain select ...it won’t get any faster.