쿼리 순서 섞기

쿼리는 shuffle 전략을 지원하는 shuffle 연산자 집합과 함께 사용되는 의미 체계 유지 변환입니다. 관련된 데이터에 따라 전략을 사용하여 쿼리하면 성능이 shuffle 향상될 수 있습니다. 키(join키, 키, make-seriessummarize 키 또는 partition 키)의 카디널리티가 높고 일반 연산자 쿼리가 쿼리 제한에 도달하면 순서 섞기 쿼리 전략을 shuffle 사용하는 것이 좋습니다.

순서 섞기 명령과 함께 다음 연산자를 사용할 수 있습니다.

쿼리 전략을 사용 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) 다음에 나타납니다.

Syntax

With hint.strategy = shuffle

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

T|summarizehint.strategy = shuffleDataExpression

T|쿼리| partition hint.strategy( = shuffleSubQuery)

와 함께 hint.shufflekey =

T|DataExpression|joinhint.shufflekey = (DataExpression)

T|summarizehint.shufflekey = keyDataExpression

T|make-serieshint.shufflekey = keyDataExpression

T|쿼리| 파티션 hint.shufflekey = (SubQuery)

구문 규칙에 대해 자세히 알아보세요.

매개 변수

이름 형식 필수 설명
T string ✔️ 연산자가 데이터를 처리할 테이블 형식 원본입니다.
DataExpression string 암시적 또는 명시적 테이블 형식 변환 식입니다.
쿼리 string 변환 식은 T의 레코드에서 실행됩니다.
key string join 키, 키, summarizemake-series 키 또는 partition 키를 사용합니다.
하위 쿼리가 string 변환 식입니다.

참고

선택한 구문에 따라 DataExpression 또는 쿼리 를 지정해야 합니다.

예제

순서 섞기를 사용하여 summarize 사용

연산자를 사용하는 summarize 전략 쿼리는 shuffle 각 노드가 데이터의 한 파티션을 처리하는 모든 클러스터 노드의 부하를 공유합니다.

StormEvents
| summarize hint.strategy = shuffle count(), avg(InjuriesIndirect) by State
| 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

출력

개수
103

순서 섞기에서 메이크 시리즈 사용

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:00:00.0000000Z","2007-01-30T00:00:00.0000000Z"]
노스캐롤라이나 [20000,0,1000] ["2006-12-31T00:00:00.0000000Z","2007-01-15T00:00:00.0000000Z","2007-01-30T00:00:00.0000000Z"]
대서양 북부 [0,0,0] ["2006-12-31T00:00:00.0000000Z","2007-01-15T00:00:00.0000000Z","2007-01-30T00:00:00.0000000Z"]

순서 섞기에서 파티션 사용

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

출력

개수
22345

hint.strategy=shuffle 및 hint.shufflekey=key 비교

를 사용하면 hint.strategy=shuffle순서가 섞인 연산자가 모든 키로 섞입니다. 다음 예제에서 쿼리는 및 EventId 를 키로 사용하여 EpisodeId 데이터를 순서를 섞습니다.

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

출력

개수
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

출력

개수
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 = EpisodeId.join

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 사용하면 성능이 향상됩니다. 원본 테이블에는 150M 레코드가 있고 키별 그룹의 카디널리티는 10M이며 10개의 클러스터 노드에 걸쳐 있습니다.

전략 없이 shuffle 연산자를 사용하면 summarize 쿼리가 1:08 이후에 종료되고 메모리 사용량이 최대 3GB입니다.

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

출력

개수
1086

에서 전략을 summarize사용하는 shuffle 동안 쿼리는 ~7초 후에 종료되고 메모리 사용량이 0.43GB입니다.

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

출력

개수
1086

다음 예제에서는 60M 레코드가 있는 테이블이 있는 두 개의 클러스터 노드가 있는 클러스터의 성능을 보여 줍니다. 여기서 키별 그룹의 카디널리티는 2M입니다.

없이 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개의 노드가 있는 클러스터에서 샘플링되었습니다.

쿼리의 왼쪽 원본 테이블에는 키 카디널리티가 ~14M인 15M 레코드가 join 있습니다. 쿼리의 오른쪽 원본에는 150M 레코드가 있고 키의 join 카디널리티는 10M입니다. 쿼리는 ~28초 후에 종료되고 메모리 사용량이 1.43GB입니다.

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

연산자와 join 함께 전략을 사용하는 shuffle 경우 쿼리는 ~4초 후에 종료되고 메모리 사용량 최고는 0.3GB입니다.

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분 후에 제한 및 시간 초과에 도달합니다. 그러나 연산자와 함께 join 전략을 사용하는 shuffle 경우 쿼리는 ~34초 후에 종료되고 메모리 사용량 최고는 1.23GB입니다.

다음 예제에서는 키의 카디널리티가 2M인 60M 레코드 테이블과 함께 두 개의 클러스터 노드가 있는 클러스터의 join 개선 사항을 보여 줍니다. 없이 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