Two tables exists:
maindata = id, devid, value
(10M rows)
djournal = id, devid, md_id_begin, md_id_end, state
(10k rows)
I want to select all from maindata
for certain devid
except rows having wrong state
:
SELECT md.*
FROM maindata AS md
LEFT JOIN djournal AS dj
ON md.id BETWEEN dj.md_id_begin AND dj.md_id_end
AND md.devid = dj.devid
WHERE md.devid = 123456789
AND dj.state <> 'idle'
ORDER BY md.id ASC;
Given query produce exactly what I want, but sloooooow. All possible indices has been created.
Sure it's easy to store state
field directly in the maindata
table, but it's curious why that query is so slow and is any workaround exists?
You just have an index problem.
You didn't published the database structure, but if you ask this question, this is because you don't know much about databases (because every decent db server can show you where the query spend its time).
Your missing indexes are probably on
md_id_begin
,md_id_end
as well asstate
. Just a guess.Indexing
id
could also be a very good idea if you didn't.Sorry for disturbance, people, no solution exists for that problem. That's not a problem at all, that's a normal sql-engine's behaviour. I've try to explain why. Let we have two sets:
Let make a JOIN with no condition:
Let's straighten JOIN by "=" condition:
And when we JOIN on ">" we get:
Lax condition produce lax result. Complex condition reduce the resulting set, but significantly increase the amount of calculations. When we JOIN on BETWEEN or < or > we get huge temporary tables for intermediate results - with no indices, searched by filesort.
So, joining sets by something else than "=" - is a bad idea.