В SQLite я пытаюсь выполнить фильтрацию с помощью IN
в моем предложении WHERE
, а затем ORDER BY
. Столбцы, используемые в IN
и ORDER BY
, оба находятся в индексе, причем столбец, используемый в IN
, идет первым в индексе. Однако временное дерево в конечном итоге используется для сортировки ORDER BY
, где, как я ожидал, был бы использован индекс. Из моего чтения Обзор оптимизатора запросов SQLite , я считаю, что оптимизатор должен использовать индекс как для IN
, так и для ORDER BY
.
Чтобы быть более конкретным, у меня есть таблица базы данных, которую я использую для хранения метаданных для набора данных для обучения машинному обучению. В таблице ~ 70 миллионов строк. В каждой строке есть столбец со случайным целым числом (0–9), чтобы можно было легко разделить набор данных на 10% фрагментов (для обучения, тестирования и т. Д. c). В каждой строке также есть столбец, позволяющий предварительно перемешать случайный порядок (с использованием UUID). Тогда индекс представляет собой многостолбцовый индекс для номера разделения набора данных, за которым следует UUID в случайном порядке.
In с несколькими значениями (неожиданное использование индекса):
Упрощенный пример желаемого запроса будет выглядеть примерно так:
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4, 5)
ORDER BY "t1"."random_order_uuid";
Выполнение EXPLAIN QUERY PLAN
на этом показывает, что индекс используется для получения правильных dataset_split
s, но затем используется временное дерево для сортировки по random_order_uuid
. Я ожидал, что вместо временного дерева будет использован индекс.
Равно с одиночным значением (ожидаемое использование индекса):
Если вместо этого я попытаюсь получить одиночное dataset_split
, используя равно ...
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" = 4
ORDER BY "t1"."random_order_uuid";
тогда индекс используется как для выбора dataset_split
, так и для random_order_uuid
по желанию.
In с одним значением (неожиданное использование индекса):
Использование одиночного dataset_split
с IN
...
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4)
ORDER BY "t1"."random_order_uuid";
индексом снова используется только для выбора dataset_split
, а random_order_uuid
сортируется во временном дереве.
Равно с несколькими значениями (неожиданное использование индекса):
Если в dataset_split
используется несколько равенств, разделенных OR
с ...
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" = 4 OR "t1"."dataset_split" = 5
ORDER BY "t1"."random_order_uuid";
, то индекс используется только для выбора dataset_split
, а упорядочение выполняется с помощью временного дерева. Примечательно, что в обзоре оптимизатора указано, что несколько равенств, разделенных OR
s, будут преобразованы оптимизатором в IN
, что снова предполагает, что IN
в сочетании с ORDER BY
является проблемой.
В с несколькими значениями без порядка (ожидаемое использование индекса):
Если ORDER BY
опущено ...
SELECT "t1"."tic_id"
FROM TessFfiLightcurveMetadata AS "t1"
WHERE "t1"."dataset_split" IN (4, 5);
, индекс используется для выбора dataset_split
.
Есть ли причина, по которой мне не хватает индекса, почему индекс не используется для обеих частей запроса с использованием IN
и ORDER BY
вместе? Я делаю неверное предположение о том, как работает оптимизация индексов? Или, возможно, я что-то не так сделал при настройке индексов / запросов?
Проверено с помощью SQLite 3.31.1