Перейти к содержимому
Последнее обновление

Введение в оптимизатор запросов

Определение одним предложением​

Оптимизатор запросов Doris (Nereids) — это современный оптимизатор запросов, построенный на основе фреймворка Cascades. Он сочетает RBO (оптимизацию на основе правил) и CBO (оптимизацию на основе стоимости), чтобы формировать эффективные планы выполнения сложных запросов.

Обзор содержания​

Перед чтением этой статьи рекомендуется ознакомиться со следующими темами:

  • Основная роль оптимизатора запросов в системе баз данных
  • Основные понятия плана выполнения SQL
  • Различие между оптимизацией на основе правил (RBO) и оптимизацией на основе стоимости (CBO)

В статье последовательно рассматриваются следующие темы:

  • Предпосылки разработки оптимизатора запросов
  • Основные преимущества оптимизатора запросов Doris
  • Общий принцип работы оптимизатора
  • Часто используемые сеансовые переменные для настройки

Предпосылки разработки​

Существующий оптимизатор запросов сталкивается с тремя категориями проблем:

ПроблемаКонкретное проявление
Высокая сложность запросовПользовательские запросы становятся всё сложнее, а сценарии их использования — всё разнообразнее
Строгие требования к работе в реальном времениПользователи ожидают немедленного получения результатов запросов
Быстрый темп развитияОптимизатор должен быстро адаптироваться к постоянно возникающим новым требованиям

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

Преимущества оптимизатора запросов Doris​

Оптимизатор запросов Doris обладает существенными преимуществами перед прежним оптимизатором по трём направлениям: он более интеллектуальный, стабильный и гибкий.

Более интеллектуальный​

  • Оптимизатор явно представляет каждое отдельное преобразование RBO и CBO в виде «правила».
  • Каждое правило содержит набор шаблонов, описывающих структуру плана запроса. Это позволяет оптимизатору точно определять планы, к которым можно применить оптимизацию.
  • Благодаря этому оптимизатор лучше поддерживает сложные запросы, например с многоуровневыми вложенными подзапросами.

Часть, отвечающая за CBO, построена на передовом фреймворке Cascades и в полной мере использует следующие три категории информации:

  1. Подробная статистика данных
  2. Информация о характеристиках данных
  3. Тщательно настроенная модель стоимости

Благодаря этой информации оптимизатор легко справляется со сложными запросами, например с соединениями множества таблиц.

Более стабильный​

  • Все правила оптимизации применяются к дереву логического плана выполнения.
  • После синтаксического и семантического анализа запрос преобразуется в древовидную структуру.
  • По сравнению с прежним оптимизатором внутренние структуры данных нового оптимизатора более продуманны и унифицированны.

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

Более гибкий​

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

Принцип работы оптимизатора​

Общая схема работы​

Принцип работы оптимизатора

Процесс работы оптимизатора можно условно разделить на следующие четыре шага:

ШагЭтапОписание
1Синтаксический анализПреобразование текста SQL в абстрактное синтаксическое дерево (AST). Если SQL корректен, обработка продолжается; в противном случае выдаётся ошибка и обработка прекращается
2Семантический анализПроверка существования таблиц, столбцов и функций в AST, а также соответствия их использования синтаксическим и семантическим правилам. Если проверка пройдена, обработка продолжается; в противном случае выдаётся ошибка и обработка прекращается
3Переписывание плана запроса (RBO)Переписывание плана запроса с помощью заранее определённых правил. Распространённые приёмы включают отсечение ненужных столбцов, проталкивание предикатов и отсечение партиций
4Оптимизация плана запроса (CBO)Перебор множества эквивалентных планов в пределах пространства поиска, оценка стоимости выполнения каждого плана и выбор плана с наименьшей стоимостью в качестве итогового плана выполнения

Цели каждого шага:

  • Синтаксический анализ: убедиться, что текст SQL можно разобрать и преобразовать в корректное AST.
  • Семантический анализ: убедиться, что объекты, на которые ссылается AST, существуют и используются корректно.
  • Переписывание RBO: повысить скорость выполнения с помощью детерминированных правил.
  • Оптимизация CBO: выбрать оптимальный план выполнения на основе модели стоимости, чтобы обеспечить наиболее эффективное выполнение запроса.

Часто используемые сеансовые переменные​

nereids_timeout_second​

ПараметрОписание
НазначениеЗадаёт максимально допустимое время планирования запроса. При превышении этого значения планирование прекращается и возвращается сообщение об ошибке
Значение по умолчанию30s
Сценарий использованияЕсли запрос обращается к большому количеству внешних таблиц или сам запрос особенно сложен, увеличьте это значение до подходящего уровня, чтобы обеспечить нормальную обработку запроса

Цель механизма: во время планирования запроса система устанавливает блокировки на чтение для всех таблиц, задействованных в SQL. Основные цели ограничения времени планирования:

  • Поддерживать стабильность кластера
  • Предотвращать чрезмерное потребление ресурсов из-за слишком долгого планирования
  • Избегать конфликтов блокировок

Рекомендации по настройке:

  • При возникновении ошибки превышения времени планирования сначала проверьте, не слишком ли сложен SQL и не задействовано ли в нём слишком много таблиц.
  • Если вы убедились, что такая сложность запроса оправданна, увеличьте это значение с помощью SET nereids_timeout_second = <seconds>;.