日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

SQL性能問題

本文介紹有關SQL性能相關的常見問題。

實時計算Flink版如何拆分SQL作業節點?

運維中心 > 作業運維頁面,單擊目標作業名稱,在部署詳情頁簽的運行參數配置區域的其他配置中,添加如下代碼后保存生效。

pipeline.operator-chaining: 'false'

Group Aggregate優化技巧有哪些?

  • 開啟MiniBatch(提升吞吐)

    MiniBatch是緩存一定的數據后再觸發處理,以減少對State的訪問,從而提升吞吐并減少數據的輸出量。

    MiniBatch主要基于事件消息來觸發微批處理,事件消息會按您指定的時間間隔在源頭插入。

    • 適用場景

      微批處理通過增加延遲換取高吞吐,如果您有超低延遲的要求,不建議開啟微批處理。通常對于聚合場景,微批處理可以顯著地提升系統性能,建議開啟。

    • 開啟方式

      MiniBatch默認關閉,您需要在目標作業的部署詳情頁簽,運行參數配置區域的其他配置中,填寫以下代碼。

      table.exec.mini-batch.enabled: true
      table.exec.mini-batch.allow-latency: 5s

      參數解釋如下表所示。

      參數

      說明

      table.exec.mini-batch.enabled

      是否開啟mini-batch。

      table.exec.mini-batch.allow-latency

      批量輸出數據的時間間隔。

  • 開啟LocalGlobal(解決常見數據熱點問題)

    LocalGlobal本質上能夠靠LocalAgg的聚合篩除部分傾斜數據,從而降低GlobalAgg的熱點,提升性能。

    LocalGlobal優化將原先的Aggregate分成Local和Global兩階段聚合,即MapReduce模型中的Combine和Reduce兩階段處理模式。第一階段在上游節點本地攢一批數據進行聚合(localAgg),并輸出這次微批的增量值(Accumulator)。第二階段再將收到的Accumulator合并(Merge),得到最終的結果(GlobalAgg)。

    • 適用場景

      提升普通聚合(例如SUM、COUNT、MAX、MIN和AVG)的性能,以及這些場景下的數據熱點問題。

    • 使用限制

      LocalGlobal是默認開啟的,但是有以下限制:

      • 在minibatch開啟的前提下才能生效。

      • 需要使用AggregateFunction實現Merge。

    • 判斷是否生效

      觀察最終生成的拓撲圖的節點名字中是否包含GlobalGroupAggregate或LocalGroupAggregate。

  • 開啟PartialFinal(解決COUNT DISTINCT熱點問題)

    為了解決COUNT DISTINCT的熱點問題,通常需要手動改寫為兩層聚合(增加按Distinct Key取模的打散層)。目前,實時計算提供了COUNT DISTINCT自動打散,即PartialFinal優化,您無需自行改寫為兩層聚合。

    LocalGlobal優化針對普通聚合(例如SUM、COUNT、MAX、MIN和AVG)有較好的效果,對于COUNT DISTINCT收效不明顯,因為COUNT DISTINCT在Local聚合時,對于DISTINCT KEY的去重率不高,導致在Global節點仍然存在熱點問題。

    • 適用場景

      使用COUNT DISTINCT,但無法滿足聚合節點性能要求。

      重要
      • 不能在包含UDAF的Flink SQL中使用PartialFinal優化方法。

      • 數據量較少的情況,不建議使用PartialFinal優化方法,浪費資源。因為PartialFinal優化會自動打散成兩層聚合,引入額外的網絡Shuffle。

    • 開啟方式

      默認不開啟。如果您需要開啟,則需要在目標作業的部署詳情頁簽,運行參數配置區域的其他配置中,填寫以下代碼。

      table.optimizer.distinct-agg.split.enabled: true
    • 判斷是否生效

      觀察最終生成的拓撲圖,是否由原來一層的聚合變成了兩層的聚合。

  • AGG WITH CASE WHEN改寫為AGG WITH FILTER語法(提升大量COUNT DISTINCT場景性能)

    統計作業需要計算各種維度的UV,例如全網UV、來自手機客戶端的UV、來自PC的UV等等。建議使用標準的AGG WITH FILTER語法來代替CASE WHEN實現多維度統計的功能。實時計算目前的SQL優化器能分析出Filter參數,從而同一個字段上計算不同條件下的COUNT DISTINCT能共享State,減少對State的讀寫操作。性能測試中,使用AGG WITH FILTER語法來代替CASE WHEN能夠使性能提升1倍。

    • 適用場景

      對于同一個字段上計算不同條件下的COUNT DISTINCT結果的場景,性能提升很大。

    • 原始寫法

      COUNT(distinct visitor_id) as UV1 , COUNT(distinct case when is_wireless='y' then visitor_id else null end) as UV2
    • 優化寫法

      COUNT(distinct visitor_id) as UV1 , COUNT(distinct visitor_id) filter (where is_wireless='y') as UV2

TopN優化技巧有哪些?

  • TopN算法

    當TopN的輸入是非更新流(例如SLS數據源),TopN只有1種算法AppendRank。當TopN的輸入是更新流時(例如經過了AGG或JOIN計算),TopN有2種算法,性能從高到低分別是:UpdateFastRank和RetractRank。算法名字會顯示在拓撲圖的節點名字上。

    • AppendRank:對于非更新流,只支持該算法。

    • UpdateFastRank:對于更新流,最優算法。

    • RetractRank:對于更新流,保底算法。性能不佳,在某些業務場景下可優化成UpdateFastRank。

    下面介紹RetractRank如何能優化成UpdateFastRank。使用UpdateFastRank算法需要具備3個條件:

    • 輸入流為更新流。

    • 輸入流有Primary Key信息,例如上游做了GROUP BY聚合操作。

    • 排序字段的更新是單調的,且單調方向與排序方向相反。例如,ORDER BY COUNT/COUNT_DISTINCT/SUM(正數)DESC。

    如果您要獲取到UpdateFastRank的優化Plan,則您需要在使用ORDER BY SUM DESC時,添加SUM為正數的過濾條件,確保total_fee為正數。

    insert
      into print_test
    SELECT
      cate_id,
      seller_id,
      stat_date,
      pay_ord_amt  --不輸出rownum字段,能減小結果表的輸出量。
    FROM (
        SELECT
          *,
          ROW_NUMBER () OVER (
            PARTITION BY cate_id,
            stat_date  --注意要有時間字段,否則State過期會導致數據錯亂。
            ORDER
              BY pay_ord_amt DESC
          ) as rownum  --根據上游sum結果排序。
        FROM (
            SELECT
              cate_id,
              seller_id,
              stat_date,
              --重點。聲明Sum的參數都是正數,所以Sum的結果是單調遞增的,因此TopN能使用優化算法,只獲取前100個數據。
              sum (total_fee) filter (
                where
                  total_fee >= 0
              ) as pay_ord_amt
            FROM
              random_test
            WHERE
              total_fee >= 0
            GROUP
              BY cate_name,
              seller_id,
              stat_date,
              cate_id
          ) a
        ) WHERE
          rownum <= 100;
  • TopN優化方法

    • 無排名優化

      TopN的輸出結果不需要顯示rownum值,僅需在最終前端顯示時進行1次排序,極大地減少輸入結果表的數據量。無排名優化方法詳情請參見Top-N

    • 增加TopN的Cache大小

      TopN為了提升性能有一個State Cache層,Cache層能提升對State的訪問效率。TopN的Cache命中率的計算公式如下。

      cache_hit = cache_size*parallelism/top_n/partition_key_num

      例如,Top100配置緩存10000條,并發50,當您的PatitionBy的Key維度較大時,例如10萬級別時,Cache命中率只有10000*50/100/100000=5%,命中率會很低,導致大量的請求都會擊中State(磁盤),觀察state seek metric可能會有很多毛刺。性能會大幅下降。

      因此當partitionKey維度特別大時,可以適當加大TopN的cache size,相對應的也建議適當加大TopN節點的heap memory,詳情請參見配置作業部署信息

      table.exec.rank.topn-cache-size: 200000

      默認10000條,調整TopN cache到200000,那么理論命中率能達到200000*50/100/100000 = 100%

    • PartitionBy的字段中要有時間類字段

      例如每天的排名,要帶上Day字段,否則TopN的最終結果會由于State TTL產生錯亂。

有哪些高效去重方案?

實時計算的源數據在部分場景中存在重復數據,去重成為了用戶經常反饋的需求。實時計算有保留第一條(Deduplicate Keep FirstRow)和保留最后一條(Deduplicate Keep LastRow)2種去重方案。

  • 語法

    由于SQL上沒有直接支持去重的語法,還要靈活地保留第一條或保留最后一條。因此我們使用了SQL的ROW_NUMBER OVER WINDOW功能來實現去重語法。去重本質上是一種特殊的TopN。

    SELECT *
    FROM (
       SELECT *,
        ROW_NUMBER() OVER (PARTITION BY col1[, col2..]
         ORDER BY timeAttributeCol [asc|desc]) AS rownum
       FROM table_name)
    WHERE rownum = 1

    參數

    說明

    ROW_NUMBER()

    計算行號的OVER窗口函數。行號從1開始計算。

    PARTITION BY col1[, col2..]

    可選。指定分區的列,即去重的KEYS。

    ORDER BY timeAttributeCol [asc|desc])

    指定排序的列,必須是一個時間屬性的字段(即Proctime或Rowtime)。可以指定順序(Keep FirstRow)或者倒序 (Keep LastRow)。

    rownum

    僅支持rownum=1rownum<=1

    如上語法所示,去重需要兩層Query:

    1. 使用ROW_NUMBER() 窗口函數來對數據根據時間屬性列進行排序并標上排名。

      • 當排序字段是Proctime列時,Flink就會按照系統時間去重,其每次運行的結果是不確定的。

      • 當排序字段是Rowtime列時,Flink就會按照業務時間去重,其每次運行的結果是確定的。

    2. 對排名進行過濾,只取第一條,達到了去重的目的。

      排序方向可以是按照時間列的順序,也可以是倒序:

      • Deduplicate Keep FirstRow:順序并取第一條行數據。

      • Deduplicate Keep LastRow:倒序并取第一條行數據。

  • Deduplicate Keep FirstRow

    保留首行的去重策略:保留KEY下第一條出現的數據,之后出現該KEY下的數據會被丟棄掉。因為STATE中只存儲了KEY數據,所以性能較優,示例如下。

    SELECT *
    FROM (
      SELECT *,
        ROW_NUMBER() OVER (PARTITION BY b ORDER BY proctime) as rowNum
      FROM T
    )
    WHERE rowNum = 1

    以上示例是將T表按照b字段進行去重,并按照系統時間保留第一條數據。proctime在這里是源表T中的一個具有Processing Time屬性的字段。如果您按照系統時間去重,也可以將proctime字段簡化proctime()函數調用,可以省略proctime字段的聲明。

  • Deduplicate Keep LastRow

    保留末行的去重策略:保留KEY下最后一條出現的數據。保留末行的去重策略性能略優于LAST_VALUE函數,示例如下。

    SELECT *
    FROM (
      SELECT *,
        ROW_NUMBER() OVER (PARTITION BY b, d ORDER BY rowtime DESC) as rowNum
      FROM T
    )
    WHERE rowNum = 1

    以上示例是將T表按照b和d字段進行去重,并按照業務時間保留最后一條數據。rowtime在這里是源表T中的一個具有Event Time屬性的字段。

在使用內置函數時,需要注意什么?

  • 使用內置函數替換自定義函數

    實時計算的內置函數在持續的優化當中,請盡量使用內置函數替換自定義函數。實時計算對內置函數主要進行了如下優化:

    • 優化數據序列化和反序列化的耗時。

    • 新增直接對字節單位進行操作的功能。

  • KEY VALUE函數使用單字符的分隔符

    KEY VALUE的簽名:KEYVALUE(content, keyValueSplit, keySplit, keyName),當keyValueSplit和KeySplit是單字符,例如,冒號(:)、逗號(,)時,系統會使用優化算法,在二進制數據上直接尋找所需的keyName值,而不會將整個content進行切分,性能約提升30%。

  • LIKE操作注意事項

    • 如果需要進行StartWith操作,使用LIKE 'xxx%'

    • 如果需要進行EndWith操作,使用LIKE '%xxx'

    • 如果需要進行Contains操作,使用LIKE '%xxx%'

    • 如果需要進行Equals操作,使用LIKE 'xxx',等價于str = 'xxx'

    • 如果需要匹配下劃線(_),請注意要完成轉義LIKE '%seller/_id%' ESCAPE '/'。下劃線(_)在SQL中屬于單字符通配符,能匹配任何字符。如果聲明為 LIKE '%seller_id%',則不單會匹配seller_id,還會匹配seller#idsellerxidseller1id等,導致結果錯誤。

  • 慎用正則函數(REGEXP)

    正則表達式是非常耗時的操作,對比加減乘除通常有百倍的性能開銷,而且正則表達式在某些極端情況下可能會進入無限循環,導致作業阻塞,具體情況請參見Regex execution is too slow,因此建議使用LIKE。正則函數包括: