Поделиться через


Запрос 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 DataExpression | joinhint.strategy = shuffle ( )

T = | summarize hint.strategyshuffle DataExpression

Вложенный запрос T-секции hint.strategyshuffle( = | | )

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

T | DataExpression key ( DataExpression | joinhint.shufflekey = )

T hint.shufflekeysummarize = | key DataExpression

T hint.shufflekeymake-series = | key DataExpression

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

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

Параметры

Имя (название) Type Обязательно Описание
T string ✔️ Табличный источник, данные которого обрабатываются оператором.
DataExpression string Неявное или явное табличное выражение преобразования.
Запрос string Выражение преобразования выполняется в записях T.
key string join Используйте ключ, summarize ключ, make-series ключ или partition ключ.
SubQuery 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 с перетасовкой

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 Время начала
СЕВЕРНАЯ ДАКОТА [60000,0,0] ["2006-12-31T00:00:00.000000Z","2007-01-15T00:00:0000:00.0000000Z","2007-01-30T00:00:00000000Z"]
СЕВЕРНАЯ КАРОЛИНА [20000,0,1000] ["2006-12-31T00:00:00.000000Z","2007-01-15T00:00:0000:00.0000000Z","2007-01-30T00:00:00000000Z"]
АТЛАНТИЧЕСКИЙ СЕВЕР [0,0,0] ["2006-12-31T00:00:00.000000Z","2007-01-15T00:00:0000:00.0000000Z","2007-01-30T00:00:00000000Z"]

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

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

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

Count
22345

Compare hint.strategy=shufflele and hint.shufflekey=key

При использовании hint.strategy=shuffleоператор перетасовки будет перетасовыван всеми ключами. В следующем примере запрос перемешит данные с помощью обоих 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 запрос будет игнорироваться, и запрос не будет выполняться в стратегии перетасовки. Например, в следующем примере соединение содержит сводку в левой части, поэтому использование 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 ...
... ... ... ... ... ...

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

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 ключа составляет ~14M. Правый источник запроса содержит 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, а кратность ключа составляет ~100M.

Запрос только с оператором 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