Как принудительно указать последовательность применяемых индексов в запросах?

В СУБД ЛИНТЕР достаточно жесткий порядок вычисления предикатов в запросах. Есть способы влиять на него, но в ограниченных пределах.

Рекомендации по оптимизации SQL-запросов для СУБД ЛИНТЕР описаны здесь: «СУБД ЛИНТЕР. Рекомендации по настройке СУБД ЛИНТЕР», пункт «Оптимизация SQL-запросов».

Хинты, которые влияют на вычисление запросов, описаны здесь: «СУБД ЛИНТЕР. Справочник по SQL», пункт «Управление оптимизацией выполнения запросов».

Про трассировку порядка вычисления запросов здесь: «СУБД ЛИНТЕР. Справочник по SQL», пункт «Управление трассировкой выполняемых запросов».

Далее в общем виде описывается схема вычисления SELECT-запрос в СУБД ЛИНТЕР.

Предположим простой случай, есть запрос типа "SELECT ... FROM T1, T2, ...,TN WHERE условие" (в случае наличия внешних соединений запрос также преобразуется к этому виду, а признаками внешнего соединения помечаются отдельные предикаты).

1 этап.

Вычисляются ответы на те предикаты, которые зависят только от одной из участвующих таблиц (однопеременные).

Часть этих предикатов может быть отложена для вычисления на 4-й этап (переборный) - если они сочтены малоселективными, обращаются к большой таблице при отсутствии соответствующего индекса и т.п.

Можно также явно перенести вычисление предиката на 4-й этап, задав для него хинт LAST (см. «СУБД ЛИНТЕР. Справочник по SQL», пункт «Подсказка о вычислении предиката последним»).

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

Результат 1-го этапа - с каждой из тех таблиц, для которой были вычислены однопеременные предикаты, связывается битвектор системных номеров отобранных строк.

2 этап.

Вычисляются ответы на те предикаты, которые зависят от двух и более участвующих таблиц (многопеременные).

При вычислении очередного много переменного предиката по возможности используются результаты ранее вычисленных предикатов на участвующие таблицы - как однопеременных, так и многопеременных.

Используются индексы на участвующие столбцы, при необходимости (если нужного индекса нет или в результате предыдущей работы количество отобранных из него записей мало) строятся временные индексы.

Аналогично 1 этапу, часть этих предикатов может быть отложена для вычисления на 4-й этап (переборный) - если они сочтены малоселективными, обращаются к большой таблице при отсутствии соответствующего индекса или помечены хинтом LAST.

Результат 2-го этапа - для каждого вычисленного многопеременного предиката создается вектор пар (троек и т.д.) системных номеров записей участвующих таблиц.

3 этап.

Сливаются результаты вычисления многопеременных предикатов.

Здесь важен порядок такого слияния, т.к. в результате неверного выбора порядка может получиться большой промежуточный ответ.

Для управления порядком слияния результатов предикатов служит хинт PREDORDER (см. «СУБД ЛИНТЕР. Справочник по SQL», пункт «Подсказка очередности слияния результатов вычисления предикатов»).

Результат 3-го этапа - для запроса создается общий вектор пар (троек и т.д.) системных номеров записей участвующих таблиц по результатам всех вычисленных предикатов.

4 этап.

Вычисление перебором всех оставшихся невычисленными на предыдущих этапах предикатов.

Из результата 3-го этапа исключаются пары (тройки и т.д.) системных номеров записей участвующих таблиц, которые не удовлетворяют оставшимся предикатам.

В этой грубо описанной схеме не учтены возможности наличия в запросах внешних ссылок, соединения предикатов не только по AND, но и по OR, и т.д. В таких случаях алгоритм усложняется, но в отдельных его этапах выделяются те же стадии.

Общий вывод по изложенному выше.

СУБД ЛИНТЕР обладает не столь мощными средствами оптимизации запросов, как некоторые другие СУБД, однако в 90% проблемных случаев можно с помощью перечисленных выше средств добиться приемлемой скорости выполнения запроса.

Если же этого сделать не удается, то в 99% оставшихся случаев можно переписать проблемный запрос - заменить его эквивалентным по результату с учетом особенностей СУБД ЛИНТЕР, и переписанный запрос будет опять же работать с приемлемой скоростью.

При проблемах с каким-то конкретным запросом, можно прислать в техническую поддержку СУБД ЛИНТЕР схемы участвующих в запросе таблиц, количество строк в них, и, возможно, информацию о распределении значений в участвующих в условии столбцах - тогда техническая поддержка сможет дать рекомендации по оптимизации этого запроса.