consulta shuffle

A shuffle consulta é uma transformação de preservação semântica usada com um conjunto de operadores que dão suporte à shuffle estratégia. Dependendo dos dados envolvidos, a consulta com a shuffle estratégia pode gerar melhor desempenho. É melhor usar a estratégia de consulta aleatória quando a shuffle chave (uma join chave, summarizemake-series chave ou partition chave) tem uma cardinalidade alta e a consulta de operador regular atinge os limites de consulta.

Você pode usar os seguintes operadores com o comando shuffle:

Para usar a shuffle estratégia de consulta, adicione a expressão hint.strategy = shuffle ou hint.shufflekey = <key>. Quando você usar hint.strategy=shuffle, os dados do operador serão embaralhados por todas as chaves. Use essa expressão quando a chave composta for exclusiva, mas cada chave não for exclusiva o suficiente, portanto, você embaralhará os dados usando todas as chaves do operador embaralhado.

Ao particionar dados com a estratégia de embaralhamento, a carga de dados é compartilhada em todos os nós de cluster. Cada nó processa uma partição dos dados. O número padrão de partições é igual ao número de nós de cluster.

O número de partição pode ser substituído usando a sintaxe hint.num_partitions = total_partitions, que controlará o número de partições. Isso é útil quando o cluster tem um pequeno número de nós de cluster e o número de partições padrão será pequeno e a consulta falhará ou levará um longo tempo de execução.

Observação

O uso de muitas partições pode consumir mais recursos de cluster e degradar o desempenho. Escolha o número de partição com cuidado, começando com o hint.strategy = shuffle e comece a aumentar as partições gradualmente.

Em alguns casos, o hint.strategy = shuffle será ignorado e a consulta não será executada em shuffle estratégia. Isso pode ocorrer quando:

  • O join operador tem outro shuffleoperador compatível (join, summarizeou make-seriespartition) no lado esquerdo ou direito.
  • O summarize operador aparece após outro shuffleoperador compatível (join, summarizeou make-seriespartition) na consulta.

Syntax

Com hint.strategy = shuffle

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

T|summarizehint.strategy = shuffleDataExpression

T|Consulta|SubConsulta de partição hint.strategy = shuffle()

Com hint.shufflekey = chave

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

T|summarizehint.shufflekey = chaveDataExpression

T|make-serieshint.shufflekey = chaveDataExpression

T|Consulta|SubConsulta dechave( de partição hint.shufflekey = )

Parâmetros

Nome Type Obrigatório Descrição
T string A fonte tabular cujos dados devem ser processados pelo operador .
DataExpression string Uma expressão de transformação tabular implícita ou explícita.
Consulta string Uma expressão de transformação executada nos registros de T.
chave string Use uma join chave, summarize chave, make-series chave ou partition chave.
Subconsulta string Uma expressão de transformação.

Observação

DataExpression ou Query devem ser especificados dependendo da sintaxe escolhida.

Exemplos

Usar summarize com shuffle

A shuffle consulta de estratégia com summarize o operador compartilhará a carga em todos os nós de cluster, em que cada nó processará uma partição dos dados.

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

Saída

Contagem
67

Usar junção com shuffle

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

Saída

Contagem
103

Usar make-series com shuffle

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

Saída

Estado sum_DamageProperty StartTime
DAKOTA DO NORTE [60000,0,0] ["2006-12-31T00:00:00.0000000Z","2007-01-15T00:00:00.0000000Z","2007-01-30T00:00:00.0000000Z"]
CAROLINA DO NORTE [20000,0,1000] ["2006-12-31T00:00:00.0000000Z","2007-01-15T00:00:00.0000000Z","2007-01-30T00:00:00.0000000Z"]
ATLÂNTICO NORTE [0,0,0] ["2006-12-31T00:00:00.0000000Z","2007-01-15T00:00:00.0000000Z","2007-01-30T00:00:00.0000000Z"]

Usar partição com embaralhamento

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

Saída

Contagem
22345

Comparar hint.strategy=shuffle e hint.shufflekey=key

Quando você usar hint.strategy=shuffle, o operador embaralhado será embaralhado por todas as chaves. No exemplo a seguir, a consulta embaralha os dados usando e EpisodeIdEventId como chaves:

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

Saída

Contagem
14

A consulta a seguir usa hint.shufflekey = key. A consulta acima é equivalente a essa consulta.

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

Saída

Contagem
14

Embaralhar os dados com várias chaves

Em alguns casos, o hint.strategy=shuffle será ignorado e a consulta não será executada em uma estratégia aleatória. Por exemplo, no exemplo a seguir, a junção resumiu no lado esquerdo, portanto, usar hint.strategy=shuffle não aplicará a estratégia de embaralhamento à consulta:

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

Saída

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

Para superar esse problema e executar em uma estratégia aleatória, escolha a chave que é comum para as summarize operações e join . Nesse caso, essa chave é EpisodeId. Use a dica hint.shufflekey para especificar a chave de ordem aleatória no join para hint.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

Saída

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

Usar resumir com ordem aleatória para melhorar o desempenho

Neste exemplo, usar o operador com shuffle estratégia melhora o summarize desempenho. A tabela de origem tem registros de 150M e a cardinalidade do grupo por chave é de 10M, que é distribuída em 10 nós de cluster.

Usando summarize o operador sem shuffle estratégia, a consulta termina após 1:08 e o pico de uso da memória é de ~3 GB:

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

Saída

Contagem
1086

Ao usar shuffle a estratégia com summarize, a consulta termina após ~7 segundos e o pico de uso de memória é de 0,43 GB:

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

Saída

Contagem
1086

O exemplo a seguir demonstra o desempenho em um cluster que tem dois nós de cluster, com uma tabela que tem registros de 60M, em que a cardinalidade do grupo por chave é de 2M.

Executar a consulta sem hint.num_partitions usará apenas duas partições (como número de nós de cluster) e a consulta a seguir levará aproximadamente 1:10 minutos:

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

Se definir o número de partições como 10, a consulta terminará após 23 segundos:

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

Usar junção com embaralhamento para melhorar o desempenho

O exemplo a seguir mostra como usar shuffle a estratégia com o operador melhora o join desempenho.

Os exemplos foram amostrados em um cluster com 10 nós em que os dados são distribuídos por todos esses nós.

A tabela de origem do lado esquerdo da consulta tem registros de 15M em que a cardinalidade da join chave é ~14M. A origem do lado direito da consulta tem registros de 150M e a cardinalidade da join chave é de 10M. A consulta termina após ~28 segundos e o pico de uso da memória é de 1,43 GB:

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

Ao usar shuffle a estratégia com um join operador, a consulta termina após ~4 segundos e o pico de uso de memória é de 0,3 GB:

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

Em outro exemplo, tentamos as mesmas consultas em um conjunto de dados maior com as seguintes condições:

  • A origem do lado esquerdo do join é de 150M e a cardinalidade da chave é de 148M.
  • A origem do lado direito do join é 1,5B e a cardinalidade da chave é ~100M.

A consulta apenas com o join operador atinge os limites de Data Explorer do Azure e atinge o tempo limite após 4 minutos. No entanto, ao usar shuffle a estratégia com o join operador , a consulta termina após ~34 segundos e o pico de uso de memória é de 1,23 GB.

O exemplo a seguir mostra a melhoria em um cluster que tem dois nós de cluster, com uma tabela de registros de 60M, em que a cardinalidade da join chave é de 2M. Executar a consulta sem hint.num_partitions usará apenas duas partições (como número de nós de cluster) e a consulta a seguir levará aproximadamente 1:10 minutos:

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

Ao definir o número de partições como 10, a consulta terminará após 23 segundos:

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