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

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

Подсказки для обработки перекоса помогают сократить длительное выполнение отдельных экземпляров, вызванное несколькими горячими ключами. Doris поддерживает добавление соли при соединениях, распределение DISTINCT-агрегирования по бакетам и стратегии сортировки для оконных функций, сохраняя результаты SQL. Используйте их, когда профили выполнения показывают перекос; репликация и дополнительные операции shuffle также увеличивают затраты.

примечание

Три формы подсказок, описанные на этой странице, доступны в Doris 4.1.0. Проверьте план выполнения используемой версии, чтобы убедиться, что переписывание применяется.

Подготовка данных​

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

CREATE TABLE skew_left (id INT, k INT, v INT)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES ("replication_num"="1");
CREATE TABLE skew_right (id INT, k INT, v INT)
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 1
PROPERTIES ("replication_num"="1");
INSERT INTO skew_left VALUES (1,1,10),(2,1,20),(3,2,30),(4,3,40);
INSERT INTO skew_right VALUES (1,1,100),(2,2,200);

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

Для известных горячих ключей соединения используйте shuffle[skew(<column>(<literal>, ...))]. Doris добавляет случайную соль к горячим строкам на одной стороне, реплицирует соответствующие строки на другой стороне для всех значений соли и выполняет shuffle по исходному ключу вместе с солью.

  • Для обычных соединений INNER и LEFT горячий столбец должен находиться на левой стороне. Для соединений RIGHT он должен находиться на правой стороне. Варианты ASOF INNER/LEFT/RIGHT подчиняются соответствующему правилу выбора стороны и по-прежнему требуют MATCH_CONDITION и ключей соединения по равенству.
  • Столбец должен быть указан напрямую в ключе соединения по равенству. Выражения, приведения типов и столбцы вне ключей равенства не вызывают переписывание. Подсказка требует shuffle; соединения Mark, FULL, SEMI и ANTI исключены.
  • За одно переписывание обрабатывается один указанный горячий столбец. Перекос с обеих сторон всё равно может приводить к затратам на репликацию и очень большому результату соединения.

Укажите подсказку в соединении:

SELECT l.id AS left_id, r.id AS right_id
FROM skew_left l
JOIN[shuffle[skew(l.k(1))]] skew_right r ON l.k = r.k
ORDER BY left_id, right_id;
left_id  right_id
1 1
2 1
3 2

В LEADING можно задать такое же распределение и тот же горячий ключ:

SELECT /*+ leading(l shuffle[skew(l.k(1))] r) */
l.id AS left_id, r.id AS right_id
FROM skew_left l JOIN skew_right r ON l.k = r.k
ORDER BY left_id, right_id;
left_id  right_id
1 1
2 1
3 2

Здесь l.k обозначает горячий столбец, а 1 задаёт его известное горячее значение. Используйте литералы, совместимые с типом столбца. Если порядок соединений меняется, убедитесь, что горячий столбец остаётся на нужной стороне.

Подсказка для обработки перекоса при DISTINCT-агрегировании​

Поместите [skew] перед аргументом DISTINCT-агрегата с одним аргументом:

SELECT k, COUNT(DISTINCT [skew] id) AS distinct_ids
FROM skew_left
GROUP BY k
ORDER BY k;
k  distinct_ids
1 2
2 1
3 1

Поддерживаются функции COUNT, SUM, SUM0 и GROUP_CONCAT с одним аргументом. Для переписывания необходимы GROUP BY, ровно одна агрегатная функция и один аргумент DISTINCT на этом уровне, а также прямая ссылка на столбец в качестве аргумента, причём этот аргумент не должен уже входить в GROUP BY. В противном случае Doris сохраняет обычное агрегирование. При переписывании дедупликация распределяется по ключам группировки и хеш-бакетам, после чего результаты объединяются по исходным ключам группировки. Это снижает нагрузку от горячих групп с высоким NDV.

Подсказка для обработки перекоса в оконных функциях​

Поместите [skew] после PARTITION BY в определении окна:

SELECT id, SUM(v) OVER (
PARTITION BY [skew] k ORDER BY id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS running_sum
FROM skew_left
ORDER BY id;
id  running_sum
1 10
2 30
3 30
4 40

Эта стратегия сначала выполняет локальную сортировку, затем shuffle по ключам разбиения и слияние отсортированных потоков. В группе с одинаковыми ключами разбиения её использует только самый нижний оконный узел, которому нужен shuffle; вышележащие узлы повторно используют распределение и порядок сортировки. Глобальное окно без PARTITION BY не получает параллелизма на уровне разделов, а обработка одного очень большого раздела по-прежнему может быть медленной.

Параметры​

ПараметрТипПо умолчаниюДиапазон и действие
skew_rewrite_join_salt_explode_factorЦелочисленный параметр сессии00 включает автоматический выбор на основе BE/CPU; от 1 до 65535 задаёт множитель соли/репликации. Он не зависит от количества бакетов таблицы
skew_rewrite_agg_bucket_numЦелочисленный параметр сессии1024От 1 до 65535, задаёт число хеш-бакетов для переписывания DISTINCT

Проверка и рекомендации​

Добавьте EXPLAIN перед SELECT в примере и проверьте принятые подсказки, а также добавленные узлы соли, агрегирования или сортировки. Включите enable_profile=true и сравните количество строк, время выполнения, использование памяти и объём данных shuffle в байтах для каждого экземпляра при выполнении одного и того же SQL. Подсказка может оказаться неприменимой; по итоговому плану можно определить, произошло ли переписывание.

Выбирайте горячие значения по фактическим данным. Начните с автоматического добавления соли при соединении: более высокие множители увеличивают число реплицируемых строк на другой стороне и могут повышать нагрузку на сеть и потребление памяти или приводить к OOM. Избыточное число бакетов агрегирования увеличивает затраты на shuffle и слияние. Обработка перекоса в оконных функциях оптимизирует сортировку, а не уменьшает необходимое количество строк. Повторяйте измерения при изменении распределения данных.