Запрос shuffle

Запрос shuffle — это семантическое преобразование, используемое с набором операторов, поддерживающих стратегию shuffle . В зависимости от используемых данных запросы со стратегией shuffle могут повысить производительность. Лучше использовать стратегию перемешиваемого запроса, если shuffle ключ( join ключ, summarize ключ, make-series ключ или partition ключ) имеет высокую кратность, а обычный запрос оператора достигает пределов запроса.

С командой перемешиванию можно использовать следующие операторы:

Чтобы использовать стратегию shuffle запроса, добавьте выражение hint.strategy = shuffle или hint.shufflekey = <key>. При использовании hint.strategy=shuffleданные оператора будут перемешаны всеми ключами. Используйте это выражение, если составной ключ уникален, но каждый ключ недостаточно уникален, поэтому вы будете тасовать данные, используя все ключи перемешиваемого оператора.

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

Номер секции можно переопределить с помощью синтаксиса hint.num_partitions = total_partitions, который будет управлять количеством секций. Это полезно, если кластер имеет небольшое количество узлов кластера, а число секций по умолчанию будет небольшим, а запрос завершается сбоем или занимает много времени выполнения.

Примечание

Использование нескольких секций может потреблять больше ресурсов кластера и снижать производительность. Тщательно выберите номер секции, начиная с hint.strategy = shuffle и начните постепенно увеличивать секции.

В некоторых случаях hint.strategy = shuffle объект игнорируется, и запрос не выполняется в shuffle стратегии. Это может произойти в следующих случаях:

  • Оператор join имеет другой shuffleсовместимый оператор (join, summarizemake-series или partition) слева или справа.
  • Оператор summarize отображается после другого shuffleсовместимого оператора (join, summarizemake-series или partition) в запросе.

Синтаксис

С hint.strategy = shuffle

T|DataExpression|joinhint.strategy = shuffle(DataExpression)

T|summarizehint.strategy = shuffleDataExpression

T|Запроса|SubQuery partition hint.strategy = shuffle()

С hint.shufflekey = помощью клавиши

T|DataExpression|joinhint.shufflekey = Ключ(DataExpression)

T|summarizehint.shufflekey = keyDataExpression

T|make-serieshint.shufflekey = keyDataExpression

T|Запроса|Вложенный запросключа( секции hint.shufflekey = )

Дополнительные сведения о соглашениях о синтаксисе.

Параметры

Имя Тип Обязательно Описание
T string ✔️ Табличный источник, данные которого должны обрабатываться оператором .
DataExpression string Неявное или явное табличное выражение преобразования.
Запрос string Выражение преобразования выполняется для записей T.
key string join Используйте ключ, summarize ключ, make-series ключ или partition ключ.
Вложенный запрос string Выражение преобразования.

Примечание

В зависимости от выбранного синтаксиса необходимо указать DataExpression или Query .

Примеры

Использование суммы с перемешивкой

Стратегический shuffle запрос с summarize оператором распределяет нагрузку на все узлы кластера, где каждый узел обрабатывает одну секцию данных.

StormEvents
| summarize hint.strategy = shuffle count(), avg(InjuriesIndirect) by State
| count 

Выходные данные

Count
67

Использование соединения с перемешивкой

StormEvents
| where State has "West"
| where EventType has "Flood"
| join hint.strategy=shuffle 
    (
    StormEvents
    | where EventType has "Hail"
    | project EpisodeId, State, DamageProperty
    )
    on State
| count

Выходные данные

Count
103

Использование make-series с перемешивкой

StormEvents
| where State has "North"
| make-series hint.shufflekey = State sum(DamageProperty) default = 0 on StartTime in range(datetime(2007-01-01 00:00:00.0000000), datetime(2007-01-31 23:59:00.0000000), 15d) by State

Выходные данные

Состояние sum_DamageProperty StartTime
СЕВЕРНАЯ ДАКОТА [60000,0,0] ["2006-12-31T00:00:00.0000000Z","2007-01-15T00:100:00.0000000Z","2007-01-30T00:00:00.000000Z"]
СЕВЕРНАЯ КАРОЛИНА [20000,0,1000] ["2006-12-31T00:00:00.0000000Z","2007-01-15T00:100:00.0000000Z","2007-01-30T00:00:00.000000Z"]
АТЛАНТИКА СЕВЕРНАЯ [0,0,0] ["2006-12-31T00:00:00.0000000Z","2007-01-15T00:100:00.0000000Z","2007-01-30T00:00:00.000000Z"]

Использование секции с перемешивкой

StormEvents
| partition hint.strategy=shuffle by EpisodeId
(
    top 3 by DamageProperty
    | project EpisodeId, State, DamageProperty
)
| count

Выходные данные

Count
22345

Сравните hint.strategy=shuffle и hint.shufflekey=key

При использовании hint.strategy=shuffleоператор shuffled будет перемешиван всеми ключами. В следующем примере запрос перемешит данные, используя как ключи, так EpisodeId и EventId :

StormEvents
| where StartTime > datetime(2007-01-01 00:00:00.0000000)
| join kind = inner hint.strategy=shuffle (StormEvents | where DamageCrops > 62000000) on EpisodeId, EventId
| count

Выходные данные

Count
14

В следующем запросе используется ключевое слово hint.shufflekey = key. Приведенный выше запрос эквивалентен этому запросу.

StormEvents
| where StartTime > datetime(2007-01-01 00:00:00.0000000)
| join kind = inner hint.shufflekey = EpisodeId hint.shufflekey = EventId (StormEvents | where DamageCrops > 62000000) on EpisodeId, EventId

Выходные данные

Count
14

Перетасовка данных с помощью нескольких ключей

В некоторых случаях hint.strategy=shuffle будет игнорироваться, и запрос не будет выполняться в стратегии тасовки. Например, в следующем примере соединение содержит summarize слева, поэтому при использовании hint.strategy=shuffle не будет применяться стратегия перетасовки к запросу:

StormEvents
| where StartTime > datetime(2007-01-01 00:00:00.0000000)
| summarize count() by EpisodeId, EventId
| join kind = inner hint.strategy=shuffle (StormEvents | where DamageCrops > 62000000) on EpisodeId, EventId

Выходные данные

EpisodeId EventId ... EpisodeId1 EventId1 ...
1030 4407 ... 1030 4407 ...
1030 13721 ... 1030 13721 ...
2477 12530 ... 2477 12530 ...
2103 10237 ... 2103 10237 ...
2103 10239 ... 2103 10239 ...
... ... ... ... ... ...

Чтобы устранить эту проблему и выполнить стратегию перетасовки, выберите ключ, который является общим для операций summarize и join . В данном случае этот ключ имеет значение EpisodeId. Используйте подсказкуhint.shufflekey, чтобы указать ключ перетасовки в :joinhint.shufflekey = EpisodeId

StormEvents
| where StartTime > datetime(2007-01-01 00:00:00.0000000)
| summarize count() by EpisodeId, EventId
| join kind = inner hint.shufflekey=EpisodeId (StormEvents | where DamageCrops > 62000000) on EpisodeId, EventId

Выходные данные

EpisodeId EventId ... EpisodeId1 EventId1 ...
1030 4407 ... 1030 4407 ...
1030 13721 ... 1030 13721 ...
2477 12530 ... 2477 12530 ...
2103 10237 ... 2103 10237 ...
2103 10239 ... 2103 10239 ...
... ... ... ... ... ...

Использование суммы с перетасовкой для повышения производительности

В этом примере использование summarize оператора со shuffle стратегией повышает производительность. Исходная таблица содержит 150 млн записей, а кратность группы по ключу составляет 10 млн, что распределено по 10 узлам кластера.

При использовании summarize оператора без shuffle стратегии запрос завершается после 1:08, а пик использования памяти составляет около 3 ГБ:

orders
| summarize arg_max(o_orderdate, o_totalprice) by o_custkey 
| where o_totalprice < 1000
| count

Выходные данные

Count
1086

При использовании shuffle стратегии с summarizeзапрос завершается примерно через 7 секунд, а пик использования памяти составляет 0,43 ГБ:

orders
| summarize hint.strategy = shuffle arg_max(o_orderdate, o_totalprice) by o_custkey 
| where o_totalprice < 1000
| count

Выходные данные

Count
1086

В следующем примере показана производительность кластера с двумя узлами кластера с таблицей с 60 млн записей, где кратность группирования по ключу составляет 2 млн.

Выполнение запроса без hint.num_partitions использования будет использовать только две секции (в качестве номера узлов кластера), а следующий запрос займет около 1:10 минут:

lineitem 
| summarize hint.strategy = shuffle dcount(l_comment), dcount(l_shipdate) by l_partkey 
| consume

Если задать для номера секций значение 10, запрос завершится через 23 секунды:

lineitem 
| summarize hint.strategy = shuffle hint.num_partitions = 10 dcount(l_comment), dcount(l_shipdate) by l_partkey 
| consume

Использование соединения с перемешивать для повышения производительности

В следующем примере показано, как использование shuffle стратегии с оператором join повышает производительность.

Примеры были приведены в кластере с 10 узлами, где данные распределяются по всем этим узлам.

Левая исходная таблица запроса содержит 15 млн записей, где кратность join ключа составляет около 14 млн. Правый источник запроса содержит 150 млн записей, а кратность join ключа — 10 млн. Запрос завершается примерно через 28 секунд, а пик использования памяти составляет 1,43 ГБ:

customer
| join
    orders
on $left.c_custkey == $right.o_custkey
| summarize sum(c_acctbal) by c_nationkey

При использовании shuffle стратегии с оператором join запрос завершается примерно через 4 секунды, а пик использования памяти составляет 0,3 ГБ:

customer
| join
    hint.strategy = shuffle orders
on $left.c_custkey == $right.o_custkey
| summarize sum(c_acctbal) by c_nationkey

В другом примере мы пробуем те же запросы к большому набору данных со следующими условиями:

  • Левый join источник — 150M, а кратность ключа — 148M.
  • Правый join источник объекта — 1,5B, а кратность ключа — ~100 млн.

Запрос только с оператором join достигает пределов и времени ожидания через 4 минуты. Однако при использовании shuffle стратегии с оператором join запрос завершается примерно через 34 секунды, а пик использования памяти составляет 1,23 ГБ.

В следующем примере показано улучшение кластера с двумя узлами кластера с таблицей 60 млн записей, где кратность join ключа составляет 2 млн. Выполнение запроса без hint.num_partitions использования будет использовать только две секции (в качестве номера узлов кластера), а следующий запрос займет около 1:10 минут:

lineitem
| summarize dcount(l_comment), dcount(l_shipdate) by l_partkey
| join
    hint.shufflekey = l_partkey   part
on $left.l_partkey == $right.p_partkey
| consume

Если задать для номера секций значение 10, запрос завершится через 23 секунды:

lineitem
| summarize dcount(l_comment), dcount(l_shipdate) by l_partkey
| join
    hint.shufflekey = l_partkey  hint.num_partitions = 10    part
on $left.l_partkey == $right.p_partkey
| consume