SQLITE очень медленно работает с ORDER BY - PullRequest
0 голосов
/ 09 июня 2018

У меня есть простой запрос, такой как

SELECT * FROM "mytable" where col1="foo"

, который разрешается примерно за 0,5 секунды (приблизительно 100 результатов приблизительно из 100 000 строк файла базы данных объемом 700 МБ)

Однако,как только я добавляю ORDER BY, это занимает 120 секунд.

SELECT * FROM "mytable" where col1="foo" ORDER BY col2

Даже когда я ограничиваю результат следующим образом

SELECT * FROM (SELECT * FROM "mytable" where col1="foo" LIMIT 1) ORDER BY col2

, это занимает 120 секунд, хотя сортировать буквально нечего.

Единственное исключение - если я сортирую с ORDER BY rowid (вместо ORDER BY col2) или когда я делаю это так (0,5 секунды):

SELECT * FROM "mytable" WHERE rowid IN (SELECT rowid FROM "mytable"  WHERE col1="foo") ORDER BY col2

I VACUUM'редактировал базу данных, и я проверил целостность базы данных (хорошо), и эта проблема сохраняется.Я использую версию SQLite: 3.7.7.1, замедления появляются как в phpLITEadmin, так и в моем коде PHP.

Редактировать

EXPLAIN QUERY PLAN SELECT * FROM "mytable" WHERE col1="foo" 
selectid|order|from|detail
       0|    0|   0|SCAN TABLE mytable (~11345 rows)
EXPLAIN QUERY PLAN SELECT * FROM "mytable" WHERE col1="foo" ORDER BY col2
selectid|order|from|detail
       0|    0|   0|SEARCH TABLE mytable USING AUTOMATIC COVERING INDEX (col1=?) (~7 rows)
       0|    0|   0|USE TEMP B-TREE FOR ORDER BY

Решение

ОК, кажется, мы нашли решение: CREATE INDEX col1_idx ON "mytable" (col1) необходимо по какой-то загадочной причине.Создание индекса для col2 (столбец, по которому нужно отсортировать) не имеет значения (120 секунд для сортировки с индексом для col2 или без него).Для меня это похоже на ошибку SQLite, потому что результат запроса без индексированного столбца col1 быстрый (0,5 секунды), а сортировка одной неиндексированной строки (= вообще не сортировка) не должна занимать 120 секунд.Даже сортировка всей таблицы SELECT * FROM "mytable" ORDER BY col2 занимает SQLite всего за 7 секунд.

Также интересно: CREATE INDEX для col1 и col2 занял всего 1,5 секунды.Таким образом, даже если предположить, что причиной этого замедления является то, что SQLite автоматически создает временный индекс для запроса, он все равно не объясняет, почему SQLite так долго сортируется.

Ответы [ 2 ]

0 голосов
/ 25 мая 2019

Мы столкнулись с подобной проблемой, добавив фиктивное вычисленное значение и, используя его для сортировки, решили эту «ошибку»:

SELECT *, (col2+0) AS col2_forSort FROM "mytable" where col1="foo" ORDER BY col2_forSort

или для строки (что не было в нашем случае):

SELECT *, (col2 || "") AS col2_forSort FROM "mytable" where col1="foo" ORDER BY col2_forSort

YMMV ... Удачи!

0 голосов
/ 09 июня 2018

Так что, похоже, SQLite ошибочно полагает, что было бы дешевле создать временный индекс ( индекс автоматического покрытия ) для выполнения вашего запроса вместо сортировки в памяти.Очевидно, что построение индекса на 100 000 строк для каждого запроса - не самый оптимальный план запроса.

Очевидным решением будет добавить индекс для столбцов, для которых вы хотите выполнить запрос / сортировку.

CREATE INDEX col1_idx ON mytable (col1);
CREATE INDEX col2_idx ON mytable (col2);
...