У меня есть запрос, включающий пары строк с разницей во времени менее 2 часов (~0,08333 дня) :
SELECT mt1.*, mt2.* FROM mytable mt1, mytable mt2
WHERE ABS(JULIANDAY(mt1.date) - JULIANDAY(mt2.date)) < 0.08333
Этот запрос довольно медленный, т.е. ~ 1 секунда (в таблице ~ 10k строк).
Идея заключалась в том, чтобы использовать INDEX
. Очевидно, что CREATE INDEX id1 ON mytable(date)
ничего не улучшил, это нормально.
Затем я заметил, что магический запрос CREATE INDEX id2 ON mytable(JULIANDAY(date))
не помогло при использовании:
... WHERE ABS(JULIANDAY(mt1.date) - JULIANDAY(mt2.date)) < 0.08333
не помогло при использовании:
... WHERE JULIANDAY(mt2.date) - 0.08333 < JULIANDAY(mt1.date) < JULIANDAY(mt2.date) + 0.08333
... но значительно улучшил производительность (время запроса счастливо разделено на 50!) при использовании:
... WHERE JULIANDAY(mt1.date) < JULIANDAY(mt2.date) + 0.08333 AND JULIANDAY(mt1.date) > JULIANDAY(mt2.date) - 0.08333
Конечно, 1., 2. и 3. эквивалентны, поскольку математически
|x-y| < 0.08333 <=> y - 0.08333 < x < y + 0.08333
<=> x < y + 0.08333 AND x > y - 0.08333
Вопрос. Почему решения 1 и 2 не используют ИНДЕКС, а решение 3 использует его?
Примечание:
Я использую модуль Python + Sqlite
sqlite3
Тот факт, что решения 1. и 2. не используют индекс, подтверждается при выполнении
EXPLAIN QUERY PLAN SELECT ...
:(0, 0, 0, u'SCAN TABLE mytable AS mt1') (0, 1, 1, u'SCAN TABLE mytable AS mt2')
Решение факта 3. использует индекс, показанный при выполнении
EXPLAIN QUERY PLAN SELECT ...
:(0, 0, 1, u'SCAN TABLE mytable AS mt2') (0, 1, 0, u'SEARCH TABLE mytable AS mt1 USING INDEX id2 (<expr>>? AND <expr><?)')