59.1. Обработка запроса как сложная задача оптимизации
Среди всех реляционных операторов самым сложным для обработки и оптимизации является соединение. В первую очередь потому, что по мере увеличения числа соединений в запросе число возможных планов запроса увеличивается экспоненциально. Дополнительная сложность оптимизации связана с наличием различных методов соединения (например, в Postgres Pro это вложенный цикл, соединение по хешу и соединение слиянием) для каждого отдельного соединения и разнообразием индексов (например, в Postgres Pro это B-дерево, хеш, GiST и GIN), определяющих путь доступа к отношениям.
Традиционный оптимизатор запросов Postgres Pro выполняет почти исчерпывающий поиск во всём множестве возможных стратегий. Этот алгоритм, появившийся в СУБД IBM System R, находит порядок соединений, близкий к оптимальному, но может требовать огромного количества времени и памяти, когда число соединений оказывается большим. В результате обычный оптимизатор Postgres Pro оказывается неподходящим для запросов, в которых соединяется большое количество таблиц.
Институт автоматического управления в Техническом университете Фрайбергская горная академия, Германия, столкнулся с этими проблемами, разрабатывая систему принятия решений на основе базы знаний для обслуживания электростанций, в которой в качестве СУБД планировалось применять PostgreSQL. Для машины, делающей выводы на основе базы знаний, СУБД должна была выполнять запросы с таким количеством соединений, что использование обычного оптимизатора запросов оказалось неприемлемым.
Далее мы опишем реализацию генетического алгоритма, который решает проблему выбора порядка соединений эффективным способом для запросов с большим числом соединений.