隨機查詢

隨機查詢是一組支援隨機策略之運算子的語義保留轉換。 視實際的資料而定,此查詢可能會產生相當好的效能。

在 Kusto 中支援跳過的運算子包括 聯結摘要構成系列

使用查詢參數或,設定隨機查詢 hint.strategy = shuffle 策略 hint.shufflekey = <key>

Syntax

T | where Event=="Start" | project ActivityId, Started=Timestamp
| join hint.strategy = shuffle (T | where Event=="End" | project ActivityId, Ended=Timestamp)
  on ActivityId
| extend Duration=Ended - Started
| summarize avg(Duration)
T
| summarize hint.strategy = shuffle count(), avg(price) by supplier
T
| make-series hint.shufflekey = Fruit PriceAvg=avg(Price) default=0  on Purchase from datetime(2016-09-10) to datetime(2016-09-13) step 1d by Supplier, Fruit

此策略將會在所有叢集節點上共用負載,其中每個節點都會處理資料的一個資料分割。 當索引鍵 (索引鍵 join 、索引 summarize 鍵或索引鍵 make-series) 具有高基數且一般查詢策略達到查詢限制時,使用隨機查詢策略會很有用。

提示之間的差異。策略 = 隨機和提示。 shufflekey = 索引鍵

hint.strategy=shuffle 表示隨機運算子將會由所有索引鍵隨機標示。 例如,在此查詢中:

T | where Event=="Start" | project ActivityId, Started=Timestamp
| join hint.strategy = shuffle (T | where Event=="End" | project ActivityId, Ended=Timestamp)
  on ActivityId, ProcessId
| extend Duration=Ended - Started
| summarize avg(Duration)

洗牌資料的雜湊函式會使用索引鍵 ActivityId 和 ProcessId。

上述查詢相當於:

T | where Event=="Start" | project ActivityId, Started=Timestamp
| join hint.shufflekey = ActivityId hint.shufflekey = ProcessId (T | where Event=="End" | project ActivityId, Ended=Timestamp)
  on ActivityId, ProcessId
| extend Duration=Ended - Started
| summarize avg(Duration)

如果複合索引鍵太是唯一的,但每個索引鍵的用途都不是唯一的,請使用此索引鍵, hint 以隨機運算子的所有索引鍵來亂數據。

在某些情況下, hint.strategy=shuffle 將會忽略,而且查詢將不會以隨機的策略執行。 範例案例如下:

  • join有另一個可隨機操作的運算子 (join 、或在 summarize make-series 左邊或右邊) 。
  • summarize會出現在其他可隨機操作的運算子之後 (joinsummarizemake-series 在查詢中) 。

例如:

T
| where Event=="Start"
| project ActivityId, Started=Timestamp, numeric_column
| summarize count(), numeric_column = any(numeric_column) by ActivityId
| join
    hint.strategy = shuffle (T
    | where Event=="End"
    | project ActivityId, Ended=Timestamp, numeric_column
)
on ActivityId, numeric_column
| extend Duration=Ended - Started
| summarize avg(Duration)

在此查詢中,聯結會在其左邊摘要,因此使用 hint.strategy=shuffle 不會將隨機策略套用至查詢。 若要解決此問題並以隨機執行的策略執行,請選擇 [摘要] 和 [聯結] 中常見的金鑰。 在此情況下,此索引鍵為 ActivityId 。 使用提示 hint.shufflekey 來指定聯結上的隨機按鍵 hint.shufflekey = ActivityId

T
| where Event=="Start"
| project ActivityId, Started=Timestamp, numeric_column
| summarize count(), numeric_column = any(numeric_column) by ActivityId
| join
    hint.shufflekey = ActivityId (T
    | where Event=="End"
    | project ActivityId, Ended=Timestamp, numeric_column
)
on ActivityId, numeric_column
| extend Duration=Ended - Started
| summarize avg(Duration)
ActivityId NumericColumn hash_by_key
activity1 2 56
activity1 1 65

在隨機查詢中,預設分割區數目是叢集節點編號。 您可以使用語法來覆寫這個數位 hint.num_partitions = total_partitions ,以控制資料分割數目。

當叢集有少數叢集節點,其中的預設分割區數目也很小,而且查詢仍然失敗或花費很長的執行時間時,這個提示就很有用。

注意

有許多磁碟分割可能會耗用更多的叢集資源,並降低效能。 相反地,請從提示開始,仔細選擇資料分割編號。策略 = 隨機分割,並逐漸開始增加資料分割。

範例

下列範例將示範隨機可如何 summarize 大幅改善效能。

來源資料表具有150M 記錄,而 group by 索引鍵的基數是1千萬個,其分佈超過10個叢集節點。

summarize執行一般策略時,查詢會在1:08 之後結束,且記憶體使用量尖峰為 ~ 3 GB:

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

使用隨機 summarize 策略時,查詢會在 ~ 7 秒後結束,且記憶體使用量尖峰為 0.43 GB:

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

下列範例顯示具有兩個叢集節點的叢集上的改進、資料表具有60M 記錄,以及 group by 索引鍵的基數為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

下列範例將示範隨機可如何 join 大幅改善效能。

範例是在含有10個節點的叢集上進行取樣,其中資料會散佈在所有這些節點上。

左邊的資料表具有1,500 萬次記錄,其中索引鍵的基數 join 是 ~ 14M。 右側 join 是具有150M 記錄,而索引鍵的基數 join 為1千萬個。 執行的一般策略 join ,查詢會在 ~ 28 秒後結束,且記憶體使用量尖峰為 1.43 GB:

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

使用隨機 join 策略時,查詢會在 ~ 4 秒後結束,且記憶體使用量尖峰為 0.3 GB:

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.5 b,索引鍵的基數是 ~ 100M。

具有預設策略的查詢會 join 在4分鐘後到達 Kusto 限制和超時時間。 使用隨機 join 策略時,查詢會在 ~ 34 秒後結束,且記憶體使用量尖峰為 1.23 GB。

下列範例顯示具有兩個叢集節點的叢集上的改進、資料表具有60M 記錄,以及索引鍵的基數 join 為2M。 執行查詢時,不 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