Настройка параллелизма: руководство по настройке parallel_pipeline_task_num
Doris представляет собой среду выполнения MPP. Каждый запрос выполняется параллельно на нескольких BE, а внутри каждого BE многопоточный параллелизм дополнительно ускоряет выполнение. Все операторы (Query, DML, DDL) поддерживают параллельное выполнение.
Определение в одном предложении: parallel_pipeline_task_num управляет количеством рабочих задач, используемых для выполнения одного Fragment на одном BE.
Быстрая диагностика
Прежде чем приступать к настройке, выясните следующее:
- Подтвердили ли вы с помощью инструмента
PROFILE, что запрос ограничен ресурсами CPU? - Сколько ядер CPU у текущего BE?
- К какому типу относится запрос: точечный запрос, JOIN/агрегация, нагрузочный тест или сложный запрос?
- Используете ли вы модель таблицы Duplicate или Unique Key Merge-On-Write?
- На каком уровне вы планируете изменить настройку: SQL, сеанса или всего кластера?
Значение по умолчанию равно
0, что соответствует половине количества ядер CPU на BE. Это значение уже обеспечивает баланс использования ресурсов между отдельными и одновременно выполняемыми запросами и обычно не требует вмешательства пользователя.
Принципы настройки параллелизма
Параметр parallel_pipeline_task_num позволяет полностью использовать ресурсы многоядерных процессоров и сократить время выполнения запросов. Однако многоядерный параллелизм требует операторов Shuffle для перераспределения данных и логики синхронизации потоков, поэтому чрезмерная степень параллелизма может приводить к нерациональному расходованию ресурсов.
Таблица сценариев и рекомендуемой степени параллелизма
В таблице ниже в качестве примера используется BE с 16 ядрами CPU.
| Сценарий запроса | Типичные характеристики | Рекомендуемая степень параллелизма | Обоснование |
|---|---|---|---|
| Простая операция с одной таблицей | Точечный запрос к одной таблице, сканирование небольшого объёма данных с WHERE, возврат небольшого объёма данных с LIMIT, использование материализованного представления | 1 | Есть только один Fragment; узким местом является поток сканирования данных (с адаптивным параллелизмом), а не поток выполнения запроса |
| JOIN двух таблиц / агрегация | Большой объём данных, высокая вычислительная нагрузка, CPU загружен не полностью | 16 | Полностью использует возможности параллельного выполнения движка Pipeline; не увеличивайте значение без ограничений (например, 48 лишь добавляет накладные расходы на планирование) |
| Нагрузочный тест с большим количеством одновременных запросов | Множество запросов уже способно полностью загрузить CPU | 1 | Чрезмерная степень параллелизма лишь добавляет накладные расходы на планирование потоков и задач среды выполнения |
| Сложный запрос | Узкое место трудно определить с первой попытки | Значение по умолчанию | Подбирайте значение по данным Profile и нагрузке на машину; попробуйте последовательное снижение по схеме 4-2-1 |
Doris постоянно совершенствует адаптивные стратегии. Обычно изменять настройку рекомендуется только для конкретного сценария или на уровне SQL.
Способы настройки параллелизма запросов
Doris поддерживает ручное задание степени параллелизма запросов на трёх уровнях: SQL, сеанса и всего кластера.
Способ 1: уровень SQL (рекомендуется)
- Назначение: влияет только на один оператор SQL, обеспечивая гибкое и точное управление.
- Команда: используйте 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;
Способ 2: уровень сеанса
- Назначение: влияет на все запросы в текущем сеансе.
- Команда: задайте значение через переменные сеанса.
- Описание: все операторы SQL в сеансе используют эту степень параллелизма, включая запросы одной строки, что может снизить производительность некоторых небольших запросов.
SET parallel_pipeline_task_num = 8;
Способ 3: глобальный уровень
- Назначение: влияет на поведение по умолчанию во всём кластере.
- Команда: используйте
SET GLOBAL. - Описание: обычно используется для глобальной настройки загрузки CPU. После применения настройки
globalона действует для текущего подключения и вновь создаваемых подключений, но не влияет на другие существующие подключения. Чтобы она сразу вступила в силу для всех подключений, перезапустите FE.
SET GLOBAL parallel_pipeline_task_num = 8;
Сравнение трёх способов настройки
| Способ настройки | Область действия | Когда вступает в силу | Рекомендуемый сценарий |
|---|---|---|---|
| SQL HINT | Один оператор SQL | Сразу | Точная настройка отдельного оператора SQL (самый безопасный способ) |
| Сеанс | Текущий сеанс | Сразу | Настройка группы связанных запросов |
| Глобальный | Весь кластер | Для новых подключений | Оптимизация загрузки CPU на уровне кластера |
Шардирование данных и параллелизм
Начиная с версии 2.1, Doris позволяет задавать степень параллелизма независимо от количества шардов данных.
Сравнение версий
| Версия | Поведение | Ограничение |
|---|---|---|
| До 2.1 | Степень параллелизма ≤ количества шардов, участвующих в запросе | 5 шардов допускают не более 5 параллельных задач; большие шарды нельзя читать параллельно |
| 2.1 и более поздние | Поддерживается параллельное чтение внутри шарда (включается автоматически) | Поддерживаются только модели таблиц Duplicate и Unique Key Merge-On-Write |
Примечание: это не относится к моделям Aggregate и Unique Key Merge-On-Read; для них степень параллелизма запросов по-прежнему ограничена количеством шардов.
Примеры из практики
Пример 1: чрезмерная загрузка CPU: снижение степени параллелизма
Проблема: загрузка CPU в рабочем кластере слишком высока, что влияет на производительность запросов, требующих малого времени отклика.
Анализ причины: по умолчанию Doris стремится использовать больше ресурсов, чтобы получить результаты запроса как можно быстрее. В рабочих средах с ограниченными ресурсами это может влиять на общую стабильность.
Решение: снизьте степень параллелизма со значения по умолчанию 0 (половина количества ядер CPU) до 4.
SET GLOBAL parallel_pipeline_task_num = 4;
Результат: загрузка CPU снизилась до 60% от исходного пикового значения, что уменьшило влияние на запросы, требующие малого времени отклика.
Настройка
GLOBALдействует для текущего подключения и вновь создаваемых подключений; существующие подключения не затрагиваются. Чтобы она сразу вступила в силу для всех подключений, перезапустите FE.
Пример 2: недостаточная загрузка CPU: повышение степени параллелизма
Проблема: выполнение запроса с высокой вычислительной нагрузкой занимает 28 секунд, при этом загрузка CPU составляет лишь 60%.
Пример SQL (в левой таблице 2 млрд строк, в правой таблице 5 млн строк):
SELECT
sum(if(t2.value IS NULL, 0, 1)) AS exist_value,
sum(if(t2.value IS NULL, 1, 0)) AS no_exist_value
FROM t1
LEFT JOIN t2 ON t1.key = t2.key;
Ключевые показатели Profile:
HASH_JOIN_OPERATOR (id=3 , nereids_id=448):
- PlanInfo
- join op: LEFT OUTER JOIN(BROADCAST)[]
- equal join conjunct: (value = value)
- cardinality=2,462,330,332
- vec output tuple id: 5
- output tuple id: 5
- vIntermediate tuple ids: 4
- hash output slot ids: 16
- projections: value
- project output tuple id: 5
- BlocksProduced: sum 360.099K (360099), avg 45.012K (45012), max 45.014K (45014), min 45.011K (45011)
- CloseTime: avg 8.44us, max 13.327us, min 5.574us
- ExecTime: avg 26sec153ms, max 26sec261ms, min 26sec33ms
- InitTime: avg 7.122us, max 13.395us, min 4.541us
- MemoryUsage: sum , avg , max , min
- PeakMemoryUsage: sum 1.16 MB, avg 148.00 KB, max 148.00 KB, min 148.00 KB
- ProbeKeyArena: sum 1.16 MB, avg 148.00 KB, max 148.00 KB, min 148.00 KB
- OpenTime: avg 2.967us, max 4.120us, min 1.562us
- ProbeRows: sum 1.462330332B (1462330332), avg 182.791291M (182791291), max 182.811875M (182811875), min 182.782658M (182782658)
- ProjectionTime: avg 165.392ms, max 169.762ms, min 161.727ms
- RowsProduced: sum 1.462330332B (1462330332), avg 182.791291M (182791291), max 182.811875M (182811875), min 182.782658M (182782658)
Анализ причины:
- Основные затраты времени (
ExecTime: avg 26sec153ms) приходятся на оператор Join. - Общий объём обрабатываемых данных (
ProbeRows: 1.466 billion) огромен, что характерно для нагрузки с высокими требованиями к CPU. - Мониторинг показывает загрузку CPU лишь на 60%, что указывает на возможность ускорения.
Решение: увеличьте степень параллелизма.
SET parallel_pipeline_task_num = 16;
Сравнение результатов:
| Показатель | До | После |
|---|---|---|
| Время выполнения запроса | 28 секунд | 19 секунд |
| Загрузка CPU | 60% | 90% |
Частые вопросы
Вопрос 1: какова степень параллелизма по умолчанию?
Значение по умолчанию равно 0, что во время выполнения соответствует половине количества ядер CPU на BE.
Вопрос 2: всегда ли увеличение степени параллелизма улучшает производительность? Нет. Чрезмерная степень параллелизма создаёт накладные расходы на планирование потоков и задач среды выполнения, что может снизить производительность. Например, значение 48 на BE с 16 ядрами не даёт преимуществ.
Вопрос 3: почему SET GLOBAL не действует на существующие подключения?
GLOBAL действует только для текущего подключения и вновь создаваемых подключений; другие существующие подключения не затрагиваются. Чтобы настройка сразу вступила в силу для всех подключений, перезапустите FE.
Вопрос 4: все ли модели таблиц поддерживают параллельное чтение внутри шарда? Его поддерживают только модели Duplicate и Unique Key Merge-On-Write. Для моделей Aggregate и Unique Key Merge-On-Read степень параллелизма запросов по-прежнему ограничена количеством шардов.
Вопрос 5: как определить, ограничен ли запрос ресурсами CPU?
С помощью PROFILE определите, на какой оператор приходится основная часть ExecTime, и одновременно проверьте загрузку CPU на машине. Если CPU загружен не полностью, рассмотрите возможность увеличения степени параллелизма.
Устранение неполадок
| Симптом | Возможная причина | Рекомендация по диагностике |
|---|---|---|
| После повышения степени параллелизма запрос выполняется медленнее | Накладные расходы на планирование потоков превышают выигрыш от параллелизма | Проверьте затраты времени операторов через Profile; снижайте значение по схеме 4-2-1 |
| CPU полностью загружен, но запрос выполняется медленнее | Слишком высокая степень параллелизма вызывает переключения контекста | Снизьте степень параллелизма; при большом количестве одновременных запросов установите значение 1 |
| Глобальное изменение не вступает в силу | Существующие подключения не применили новую настройку | Перезапустите FE или переподключите клиент |
| Низкая скорость чтения больших шардов | Используется версия ниже 2.1, степень параллелизма ограничена количеством шардов | Обновитесь до версии 2.1 или более поздней и убедитесь, что используется модель таблицы Duplicate или MoW |
Итоги
Обычно изменять степень параллелизма запросов не требуется. Если настройка всё же необходима, придерживайтесь следующих принципов:
- Начните с загрузки CPU: с помощью инструмента
PROFILEопределите, ограничен ли запрос ресурсами CPU, и затем решите, нужно ли менять настройку. - Предпочитайте настройку на уровне SQL: изменение через HINT для отдельного оператора SQL является самым безопасным способом. Избегайте резких глобальных изменений.
- Учитывайте сценарий: выберите подходящее значение по таблице сценариев и рекомендуемой степени параллелизма.
- Пробуйте последовательное снижение: для сложных запросов постепенно снижайте значение по схеме 4-2-1, наблюдая за производительностью запросов и нагрузкой на машину.