SQL - Индекс не используется ни для IN, ни для ORDER BY? - PullRequest
0 голосов
/ 03 августа 2020

В 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

1 Ответ

1 голос
/ 03 августа 2020

Индекс похож на телефонную книгу - или любой другой упорядоченный список, если эта ссылка устарела.

Если вы выберете две фамилии, например «Смит» и «Ли», затем первые имена располагаются по алфавиту. Однако нет тривиального способа объединить имена, чтобы упорядочить их по имени - Захари Ли опережает Эбигейл Смит. Просто добавив их, вы получите два частично отсортированных списка.

Это то, что происходит с IN. Информация о сортировке неточна для сканирования индекса, поэтому большинство баз данных просто помещают сортировку для сортировки. это, но я, без сомнения, исправлюсь, если ошибаюсь), что может позволить оптимизацию только индекса при некоторых обстоятельствах. Хотя, честно говоря, я даже не знаю, будет ли Oracle использовать его в этом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...