Freigeben über


Shuffleabfrage

Die shuffle Abfrage ist eine semantische Transformation, die mit einer Reihe von Operatoren verwendet wird, die die shuffle Strategie unterstützen. Je nach den beteiligten Daten kann die Abfrage mit der shuffle Strategie eine bessere Leistung erzielen. Es ist besser, die Shuffle-Abfragestrategie zu verwenden, wenn der shuffle Schlüssel (schlüssel join , Schlüssel, summarize Schlüssel, make-series Schlüssel oder partition Schlüssel) eine hohe Kardinalität aufweist und die reguläre Operatorabfrage Abfragegrenzwerte erreicht.

Sie können die folgenden Operatoren mit dem Befehl "Shuffle" verwenden:

Um die shuffle Abfragestrategie zu verwenden, fügen Sie den Ausdruck hint.strategy = shuffle oder hint.shufflekey = <key>. Bei Verwendung hint.strategy=shufflewerden die Operatordaten von allen Schlüsseln neu angeordnet. Verwenden Sie diesen Ausdruck, wenn der Verbundschlüssel eindeutig ist, aber jeder Schlüssel nicht eindeutig genug ist, sodass Sie die Daten mit allen Schlüsseln des shuffled-Operators mischen.

Beim Partitionieren von Daten mit der Shuffle-Strategie wird die Datenlast auf allen Clusterknoten freigegeben. Jeder Knoten verarbeitet eine Partition der Daten. Die Standardanzahl der Partitionen entspricht der Anzahl der Clusterknoten.

Die Partitionsnummer kann mithilfe der Syntax hint.num_partitions = total_partitionsüberschrieben werden, die die Anzahl der Partitionen steuert. Dies ist nützlich, wenn der Cluster über eine kleine Anzahl von Clusterknoten verfügt und die Standardpartitionsnummer klein ist, und die Abfrage schlägt fehl oder dauert eine lange Ausführungszeit.

Hinweis

Die Verwendung vieler Partitionen verbraucht möglicherweise mehr Clusterressourcen und beeinträchtigt die Leistung. Wählen Sie die Partitionsnummer sorgfältig aus, indem Sie mit der hint.strategy = shuffle schrittweisen Erhöhung der Partitionen beginnen.

In einigen Fällen wird die hint.strategy = shuffle Abfrage ignoriert, und die Abfrage wird nicht in shuffle der Strategie ausgeführt. Dies kann passieren, wenn:

  • Der join Operator verfügt über einen anderen shufflekompatiblen Operator (join, summarizemake-series oder partition) auf der linken oder rechten Seite.
  • Der summarize Operator wird nach einem anderen shufflekompatiblen Operator (join, make-series summarizeoder partition) in der Abfrage angezeigt.

Syntax

Mit hint.strategy = shuffle

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

T = | summarize hint.strategyshuffle DataExpression

T | Query | Partition hint.strategy = (shuffleSubQuery )

Mit hint.shufflekey = Taste

T | DataExpression = join|hint.shufflekey Key ( DataExpression )

T hint.shufflekeysummarize = | key DataExpression

T hint.shufflekeymake-series = | key DataExpression

T | Query | Partition hint.shufflekey = Key ( SubQuery )

Erfahren Sie mehr über Syntaxkonventionen.

Parameter

Name Type Erforderlich Beschreibung
T string ✔️ Die tabellarische Quelle, deren Daten vom Operator verarbeitet werden sollen.
DataExpression string Ein impliziter oder expliziter Tabellarischer Transformationsausdruck.
Abfrage string Ein Transformationsausdruck wird für die Datensätze von T ausgeführt.
key string Verwenden Sie eine join Taste, summarize eine Taste, make-series eine Taste oder partition eine Taste.
SubQuery string Ein Transformationsausdruck.

Hinweis

Entweder DataExpression oder Query muss je nach ausgewählter Syntax angegeben werden.

Beispiele

Zusammenfassung mit "Shuffle" verwenden

Die shuffle Strategieabfrage mit summarize Operator teilt die Last auf allen Clusterknoten, wobei jeder Knoten eine Partition der Daten verarbeitet.

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

Ausgabe

Anzahl
67

Verwenden der Verknüpfung mit "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

Ausgabe

Anzahl
103

Verwenden von Make-Series mit 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

Ausgabe

Staat sum_DamageProperty StartTime
NORTH DAKOTA [60000,0,0] ["2006-12-31T00:00:00.000000Z","2007-01-15T00:0100:00.000000Z","2007-01-30T00:00:00.000000Z"]
NORTH CAROLINA [20000,0,1000] ["2006-12-31T00:00:00.000000Z","2007-01-15T00:0100:00.000000Z","2007-01-30T00:00:00.000000Z"]
ATLANTIC NORTH [0,0,0] ["2006-12-31T00:00:00.000000Z","2007-01-15T00:0100:00.000000Z","2007-01-30T00:00:00.000000Z"]

Verwenden der Partition mit "Shuffle"

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

Ausgabe

Anzahl
22345

Vergleichen Sie "hint.strategy=shuffle" und "hint.shufflekey=key".

Wenn Sie dies verwenden hint.strategy=shuffle, wird der shuffled-Operator von allen Tasten neu angeordnet. Im folgenden Beispiel löscht die Abfrage die Daten mit beiden EpisodeId und EventId als Schlüssel:

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

Ausgabe

Anzahl
14

Die folgende Abfrage verwendet hint.shufflekey = key. Die obige Abfrage entspricht dieser Abfrage.

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

Ausgabe

Anzahl
14

Koppeln der Daten mit mehreren Schlüsseln

In einigen Fällen wird die hint.strategy=shuffle Abfrage ignoriert, und die Abfrage wird nicht in der Shuffle-Strategie ausgeführt. Im folgenden Beispiel hat die Verknüpfung beispielsweise eine Zusammenfassung auf der linken Seite, sodass die Verwendung hint.strategy=shuffle keine Shuffle-Strategie auf die Abfrage anwendet:

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

Output

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

Um dieses Problem zu überwinden und in der Shuffle-Strategie auszuführen, wählen Sie den Schlüssel aus, der für die und join die summarize Vorgänge üblich ist. In diesem Fall ist EpisodeIddieser Schlüssel . Verwenden Sie den Hinweishint.shufflekey, um die Shuffle-Taste für folgendes hint.shufflekey = EpisodeIdjoin anzugeben:

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

Output

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

Verwenden von "Zusammenfassung" mit "Shuffle" zur Verbesserung der Leistung

In diesem Beispiel verbessert die Verwendung des Operators mit shuffle der Strategie die summarize Leistung. Die Quelltabelle verfügt über 150M-Datensätze und die Kardinalität der Gruppe nach Schlüssel beträgt 10M, die sich über 10 Clusterknoten erstreckt.

Bei Verwendung des summarize Operators ohne shuffle Strategie endet die Abfrage nach 1:08, und der Speicherauslastungs-Höchstwert beträgt ca. 3 GB:

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

Output

Anzahl
1086

Während der Verwendung der shuffle Strategie mit summarize, endet die Abfrage nach ~7 Sekunden und der Speicherauslastungs-Höchstwert beträgt 0,43 GB:

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

Output

Anzahl
1086

Das folgende Beispiel veranschaulicht die Leistung eines Clusters mit zwei Clusterknoten mit einer Tabelle mit 60M-Datensätzen, wobei die Kardinalität der Gruppe nach Schlüssel 2M ist.

Wenn Sie die Abfrage ausführen, ohne hint.num_partitions dass nur zwei Partitionen (als Clusterknotennummer) verwendet werden, dauert die folgende Abfrage ca. 1:10 Minuten:

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

Wenn die Partitionsnummer auf 10 festgelegt wird, endet die Abfrage nach 23 Sekunden:

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

Verwenden der Verknüpfung mit "Shuffle" zur Verbesserung der Leistung

Das folgende Beispiel zeigt, wie die Verwendung der shuffle Strategie mit dem Operator die join Leistung verbessert.

Die Beispiele wurden auf einem Cluster mit 10 Knoten beispielt, in denen die Daten über alle diese Knoten verteilt sind.

Die linke Quelltabelle der Abfrage verfügt über 15M-Datensätze, bei denen die Kardinalität des join Schlüssels ~14M beträgt. Die rechte Quelle der Abfrage weist 150M Datensätze auf, und die Kardinalität des join Schlüssels beträgt 10M. Die Abfrage endet nach ~28 Sekunden und der Speicherauslastungs-Höchstwert beträgt 1,43 GB:

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

Bei der Verwendung der shuffle Strategie mit einem join Operator endet die Abfrage nach ~4 Sekunden, und der Speicherauslastungs-Höchstwert beträgt 0,3 GB:

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

In einem anderen Beispiel versuchen wir dieselben Abfragen für ein größeres Dataset mit den folgenden Bedingungen:

  • Linksseitige Quelle der join 150M und die Kardinalität des Schlüssels beträgt 148M.
  • Rechtsseitige Quelle des Schlüssels join ist 1,5B, und die Kardinalität des Schlüssels beträgt ~100M.

Die Abfrage mit nur dem join Operator trifft Grenzwerte und Zeitüberschreitungen nach 4 Minuten. Wenn Sie die Strategie jedoch mit dem join Operator verwendenshuffle, endet die Abfrage nach ~34 Sekunden, und der Speicherauslastungs-Höchstwert beträgt 1,23 GB.

Das folgende Beispiel zeigt die Verbesserung auf einem Cluster mit zwei Clusterknoten mit einer Tabelle von 60M-Datensätzen, bei denen die Kardinalität des join Schlüssels 2M ist. Wenn Sie die Abfrage ausführen, ohne hint.num_partitions dass nur zwei Partitionen (als Clusterknotennummer) verwendet werden, dauert die folgende Abfrage ca. 1:10 Minuten:

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

Wenn Die Partitionsnummer auf 10 festgelegt wird, endet die Abfrage nach 23 Sekunden:

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