Улучшенный оптимизатор запросов

Улучшенный оптимизатор запросов

Оптимизатор - своего рода "мозг" сервера, и степень его интеллектуальности может кардинально повлиять на скорость работы приложений. Неверно выбранный план может привести к увеличению времени выполнения запроса в тысячи раз. За время своей эволюции от версии InterBase 4.0, не способной вообще оптимизировать явные соединения, и до последних версий в оптимизатор InterBase разработчиками Borland вносились изменения, которые хотя и приводили к улучшению планов для определенных случаев, но часто непредсказуемо сказывались на других запросах. Например, в пятой версии InterBase научился корректно оптимизировать соединения в явном синтаксисе ANSI SQL, но другой способ выборки индексов в ряде случаев приводил к катастрофическому увеличению времени выполнения запросов. Подобные неприятности появились в версии 6.0, в результате многие разработчики не могли перенести свои системы на современную платформу.

Проанализировав большое число проблемных случаев с оптимизацией InterBase версий 4.x, 5.x и 6.x, разработчики Yaffil внесли ряд улучшений, в результате чего в большинстве случаев можно вообще отказаться от применения ручных планов При этом при переходе на Yaffil со старых версий InterBase случаев ухудшения автоматических планов практически не наблюдается.

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

Перечислим некоторые улучшения оптимизатора Yaffil.

Выбор индекса с меньшим числом полей при наличии индекса с большим числом полей

Этот случай часто возникает, когда в таблице имеется большое количество индексов, в том числе составных. Оптимизатор Interbase/Firebird всегда пытался выбрать индекс, который охватывает множество полей, в то время как существовал более быстрый и компактный индекс. Оптимизатор Yaffil автоматически разрешает данную ситуацию. Вот пример: Таблица из трех полей Table 1 (Fl, F2, F3) На нее созданы три индекса: IDX_F1(F1), IDX_F1_F2(F1,F2), IDX_F1_F2_F3(F1,F2,F3) Выполняем запрос:

select * from Tablel where Fl = параметр

Получаем следующие планы для использования индексов: Interbase 6.5/FireBird 1.0:

PLAN (Т INDEX (IDX_F1_F2_F3))

Yaffil:

PLAN (T INDEX (IDX_F1))

Interbase 6.5/FireBird 1.0 используют индекс с максимальным количеством полей, хотя очевидно, что в данном случае надо использовать единственный индекс по полю F1, как это и делает Yaffil. Это очень распространенная ошибка, приводящая к замедлению выполнения запроса, обойти которую без явного планирования достаточно сложно.

Возможность использовать индекс с начальными сегментами, удовлетворяющими условию и сортировкой по остальным

Этот случай возникает, когда выборка делается по одному полю, а сортировка - по другому, при этом имеется индекс по обоим полям. Пример: пусть существует таблица из трех полей T(F1,F2,F3), есть индексы на следующие сочетания полей: на одно поле IDX_F1(F1), на два первых поля IDX_F1_F2(F1,F2), на все три поля IDX_F1_F2_F3(F1,F2,F3).

Производим запрос следующего вида:

select * from T where Fl=.. order by F2

Получаем планы следующего вида:

FireBird/InterBase 6.5:

PLAN SORT(Т INDEX (IDX_F1_F2_F3))

Yaffil:

PLAN (T ORDER (IDX_F1))

Исключение из обработки индексов с сильно различающейся селективностью

Пример: пусть у нас есть таблица из трех полей T(F1,F2,F3) с индексами на каждое поле IDX_Fl(Fl), IDX_F2(F2) и IDX_F3(F1). Пусть здесь F1 является уникальным полем (первичный ключ, например), a F2 - неуникальным. Производим запрос:

select * from Т where Fl = параметр! and F2 = параметр2 ...

В результате получаем следующие планы: FireBird/InterBase 6.5:

PLAN (Т INDEX (IDX_F1, IDX_F2))

Yaffil:

PLAN (Т INDEX (IDX_F1))

Оптимизатор Yaffil всегда объединяет индексы с учетом селективности.

Отметим, что в качестве критериев отбора индексов используется не только селективность, но и категории условий, используемых в ограничениях. Так, например, "вес" операции "=" больше, чем "вес" операций "<" и ">".