Вчера открих един ефект при SQLite, който се среща рядко, но може сериозно да намали производителността на заявките.
Ето тестов пример:
create table t1(a text unique);
create table t2(b integer);
explain query plan
select
*
from
t2 left join t1 on a = b;
Това дава следния план, въпреки, че на t1.a
има прекрасен индекс (щото е UNIQUE), той не се използва:
SCAN TABLE t2
SCAN TABLE t1
Предполагам, че това се дължи на това, че оптимизаторът, като види, че b
е integer, преобразува и a
в integer, а съществуващият индекс е текстов.
За да бъде използван този индекс, заявката следва да бъде написана така:
select
*
from
t2 left join t1 on a = cast(b as text);
Тогава планът е следния:
SCAN TABLE t2
SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)
И съответно скоростта на заявката е сериозно по-висока.
Малко ми е трудно да кажа дали това е бъг или особеност на оптимизатора на заявките, тъй като типовете в SQLite са само пожелания, но не и твърдо правило, а в едно поле на таблиците могат да се записват данни от произволен тип. Тоест, оптимизаторът следва на има това предвид и да използва най-добрият вариант на заявката.
Ще питам DRH и ако има някакво обяснение ще пиша в темата.