Настройка параллелизма
Параллелизм (parallel_pipeline_task_num) определяет количество рабочих задач, которые один Fragment использует при выполнении на BE. Это ключевой параметр для эффективного использования многоядерных CPU и сокращения времени выполнения запросов.
Что проверить перед настройкой
- Вы проверили количество ядер CPU на BE: оно определяет верхнюю границу параллелизма.
- Вы определили узкое место с помощью Profile или метрик мониторинга: вычисления, сканирование или накладные расходы на планирование задач.
- Вы понимаете характер текущей нагрузки: точечный запрос, JOIN/агрегация, нагрузочное тестирование или сложный запрос.
- При значении по умолчанию (
0, что означает половину количества ядер CPU) производительность действительно ниже ожидаемой.
Основные понятия
- Параллелизм MPP: каждый запрос выполняется параллельно на нескольких BE.
- Параллелизм внутри BE: многопоточное выполнение ускоряет обработку Fragment на одном BE.
parallel_pipeline_task_num: количество рабочих задач, которые один Fragment использует при выполнении. Значение по умолчанию0означает половину количества ядер CPU на BE.- Поддерживаемые операторы: все операторы Query, DML и DDL поддерживают параллельное выполнение.
Принципы настройки
Увеличение параллелизма не всегда улучшает производительность:
- Повышение параллелизма позволяет полностью использовать ресурсы многоядерных CPU и сократить время выполнения отдельного запроса.
- Однако оно добавляет операторы Shuffle для перераспределения данных и логику синхронизации потоков, что приводит к лишним затратам ресурсов.
- Значение по умолчанию уже обеспечивает баланс между выполнением отдельных запросов и конкурентной нагрузкой, поэтому ручная настройка обычно не требуется.
- Адаптивные стратегии Doris продолжают совершенствоваться. Предпочитайте настройку на уровне SQL или конкретного сценария, а не на глобальном уровне.
Рекомендации по настройке для разных сценариев
В следующих примерах предполагается, что BE располагает 16 ядрами CPU.
Сводная таблица сценариев
| Сценарий запроса | Рекомендуемый параллелизм | Обоснование |
|---|---|---|
Точечный запрос к одной таблице / WHERE для небольшого объёма данных / LIMIT / использование материализованного представления | 1 | В запросе есть только один Fragment. Узкое место — поток сканирования: он независим от потока выполнения запроса, а параллелизм сканирования регулируется адаптивно. Поэтому дополнительные параллельные потоки выполнения запроса не нужны. |
JOIN двух таблиц на большом наборе данных / запрос с агрегацией (интенсивные вычисления) | 16 | Нагрузка связана с вычислениями. Если CPU загружен не полностью, повышение параллелизма позволяет задействовать все ядра. Однако увеличивать его без ограничений не следует: например, значение 48 лишь добавляет накладные расходы на планирование задач. |
| Нагрузочное тестирование | 1 | Параллельно выполняющиеся запросы уже полностью загружают CPU, а избыточный параллелизм лишь добавляет накладные расходы на планирование потоков и работу механизма планирования. |
| Сложный запрос | Значение по умолчанию | Подбирайте значение с учётом Profile и нагрузки на сервер. Попробуйте поэтапно уменьшать его: 4 -> 2 -> 1, наблюдая за результатом. |
Сценарий 1: простые операции с одной таблицей
- Характеристики: один Fragment; узкое место — поток сканирования, параллелизм которого уже регулируется адаптивно.
- Рекомендация:
parallel_pipeline_task_num = 1. - Обоснование: поток сканирования и поток выполнения запроса независимы. Увеличение количества параллельных потоков выполнения запроса не ускоряет обработку, если узкое место — сканирование.
Сценарий 2: JOIN/агрегация на больших наборах данных
- Характеристики: вычислительно интенсивная нагрузка, при которой CPU загружен не полностью.
- Рекомендация: увеличьте параллелизм относительно значения по умолчанию, например задайте
parallel_pipeline_task_num = 16. - Обоснование: это позволяет использовать возможности параллельного выполнения движка Pipeline и полностью загрузить CPU. Однако увеличивать параллелизм без ограничений не следует: накладные расходы на планирование потоков и работу механизма планирования могут перевесить выигрыш.
Сценарий 3: нагрузочное тестирование
- Характеристики: одновременно выполняется достаточно запросов, чтобы они уже полностью загружали CPU.
- Рекомендация:
parallel_pipeline_task_num = 1. - Обоснование: это позволяет избежать накладных расходов на планирование, возникающих при повышении параллелизма отдельного запроса в условиях высокой конкурентной нагрузки.
Сценарий 4: сложные запросы
- Характеристики: сложный план выполнения, в котором трудно сразу определить узкое место.
- Рекомендация: начните со значения по умолчанию, затем с учётом Profile и нагрузки на сервер поэтапно изменяйте его: 4 -> 2 -> 1, наблюдая за результатом.
Способы настройки
Doris поддерживает настройку параллелизма на трёх уровнях: SQL, сессии и глобальном уровне. Приоритет настроек убывает в указанном порядке.
Сравнение способов
| Способ | Область действия | Когда применять | Риск |
|---|---|---|---|
| SQL HINT | Один оператор SQL | Настройка конкретного медленного SQL-запроса | Без побочных эффектов; предпочтительный способ |
| Переменная сессии | Текущая сессия | Группа запросов в одной сессии | Запросы к одной строке также используют эту настройку, что может снизить производительность |
| Глобальная переменная | Все новые подключения в кластере | Настройка загрузки CPU во всём кластере | Самая широкая область воздействия; применяйте с осторожностью |
Настройка на уровне SQL
-
Назначение: с помощью HINT точно задать параллелизм отдельного оператора SQL. Этот способ обеспечивает наибольшую гибкость.
-
Команда:
SELECT /*+SET_VAR(parallel_pipeline_task_num=8)*/ *
FROM nation, lineitem
WHERE lineitem.l_suppkey = nation.n_nationkey;
SELECT /*+SET_VAR(parallel_pipeline_task_num=8,runtime_filter_mode=global)*/ *
FROM nation, lineitem
WHERE lineitem.l_suppkey = nation.n_nationkey; -
Примечания: в том же HINT можно задать и другие переменные сессии, например
runtime_filter_mode.
Настройка на уровне сессии
-
Назначение: применить одинаковую настройку параллелизма ко всем операторам SQL в текущей сессии.
-
Команда:
SET parallel_pipeline_task_num = 8; -
Примечания: в пределах сессии даже точечные запросы к одной строке выполняются с этим параллелизмом, что может замедлить простые запросы.
Глобальная настройка
-
Назначение: применить настройку ко всем новым подключениям, изменив поведение по умолчанию во всём кластере.
-
Команда:
SET GLOBAL parallel_pipeline_task_num = 8; -
Примечания: используйте этот способ только тогда, когда действительно требуется изменить загрузку CPU во всём кластере. В остальных случаях сохраняйте значение по умолчанию.
Частые вопросы и устранение проблем
Вопрос 1: почему запрос стал медленнее после увеличения параллелизма?
Слишком высокий параллелизм увеличивает накладные расходы на Shuffle и синхронизацию потоков. Сам механизм планирования также требует ресурсов. Например, значение 48 на сервере с 16 ядрами практически не даёт выигрыша и лишь увеличивает затраты на планирование. Начните со значения по умолчанию и изменяйте его поэтапно: 4 -> 2 -> 1.
Вопрос 2: почему для точечного запроса к одной таблице рекомендуется параллелизм 1?
Точечный запрос к одной таблице содержит только один Fragment, а узкое место — сканирование данных. Поток сканирования и поток выполнения запроса разделены, причём параллелизм сканирования регулируется адаптивно. Поэтому увеличение parallel_pipeline_task_num не ускоряет обработку, ограниченную сканированием.
Вопрос 3: почему для нагрузочного тестирования также рекомендуется параллелизм 1?
Нагрузочное тестирование само по себе предполагает большое количество одновременно выполняющихся запросов, которые уже полностью загружают CPU. Повышение параллелизма отдельных запросов в этих условиях лишь добавляет накладные расходы на планирование потоков и работу механизма планирования.
Вопрос 4: что означает значение по умолчанию 0?
parallel_pipeline_task_num = 0 означает, что BE автоматически использует половину количества ядер CPU. Это значение обеспечивает баланс между производительностью отдельного запроса и пропускной способностью при конкурентной нагрузке. В большинстве сценариев менять его не требуется.
Вопрос 5: стоит ли задавать параллелизм глобально или использовать SQL HINT?
Предпочитайте SQL HINT для настройки отдельных медленных SQL-запросов. Используйте SET GLOBAL только после того, как убедитесь, что загрузку CPU необходимо скорректировать во всём кластере.
Связанные параметры
| Параметр | Назначение | Значение по умолчанию |
|---|---|---|
parallel_pipeline_task_num | Количество рабочих задач для одного Fragment на BE | 0 (количество ядер CPU на BE / 2) |
runtime_filter_mode | Режим работы Runtime Filter; часто настраивается вместе с параллелизмом | См. документацию по Runtime Filter |