文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  視窗函數最佳化

10.2.1.21 視窗函數最佳化

視窗函數會影響最佳化工具所考慮的策略

  • 如果子查詢具有視窗函數,則會停用子查詢的衍生表合併。子查詢一律會實體化。

  • 半聯結不適用於視窗函數最佳化,因為半聯結適用於 WHEREJOIN ... ON 中的子查詢,而這些子查詢不能包含視窗函數。

  • 最佳化工具會依序處理具有相同排序需求的複數個視窗,因此可以略過第一個視窗之後的視窗排序。

  • 最佳化工具不會嘗試合併可以在單一步驟中評估的視窗(例如,當多個 OVER 子句包含相同的視窗定義時)。解決方法是在 WINDOW 子句中定義視窗,並在 OVER 子句中參考視窗名稱。

未使用為視窗函數的彙總函數會在最外層的可能查詢中彙總。例如,在此查詢中,MySQL 看到 COUNT(t1.b) 因為其在 WHERE 子句中的位置,而無法存在於外部查詢中

SELECT * FROM t1 WHERE t1.a = (SELECT COUNT(t1.b) FROM t2);

因此,MySQL 會在子查詢內部進行彙總,將 t1.b 視為常數,並傳回 t2 的資料列計數。

WHERE 替換為 HAVING 會導致錯誤

mysql> SELECT * FROM t1 HAVING t1.a = (SELECT COUNT(t1.b) FROM t2);
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1
of SELECT list contains nonaggregated column 'test.t1.a'; this is
incompatible with sql_mode=only_full_group_by

發生錯誤的原因是 COUNT(t1.b) 可以存在於 HAVING 中,因此會使外部查詢彙總。

視窗函數(包括用作視窗函數的彙總函數)沒有先前的複雜性。它們總是在它們撰寫的子查詢中彙總,而絕不會在外部查詢中彙總。

視窗函數的評估可能會受到 windowing_use_high_precision 系統變數值的影響,該變數決定是否在計算視窗操作時不損失精度。預設情況下,windowing_use_high_precision 為啟用狀態。

對於某些移動框架聚合,可以應用反向聚合函數從聚合中移除值。這可以提高效能,但可能會損失精度。例如,將一個非常小的浮點數值加到一個非常大的數值上,會導致這個非常小的數值被大的數值 隱藏。當稍後反轉大的數值時,小數值的影響就會遺失。

由於反向聚合造成的精度損失僅對浮點數(近似值)資料類型上的操作是一個因素。對於其他類型,反向聚合是安全的;這包括 DECIMAL,它允許小數部分但屬於精確值類型。

為了更快的執行速度,MySQL 在安全的情況下始終使用反向聚合。

  • 對於浮點數值,反向聚合並不總是安全,可能會導致精度損失。預設情況下,會避免使用反向聚合,這樣雖然較慢但可以保留精度。如果允許為了速度而犧牲安全性,可以停用 windowing_use_high_precision 來允許反向聚合。

  • 對於非浮點數資料類型,反向聚合始終是安全的,並且無論 windowing_use_high_precision 的值為何,都會使用。

  • windowing_use_high_precision 對於 MIN()MAX() 沒有影響,因為在任何情況下它們都不使用反向聚合。

對於變異數函數 STDDEV_POP()STDDEV_SAMP()VAR_POP()VAR_SAMP() 及其同義詞的評估,可能會以最佳化模式或預設模式進行。最佳化模式可能會在最後有效位數產生略微不同的結果。如果允許這種差異,可以停用 windowing_use_high_precision 來允許最佳化模式。

對於 EXPLAIN,視窗化的執行計畫資訊太過廣泛,無法以傳統的輸出格式顯示。要查看視窗化資訊,請使用 EXPLAIN FORMAT=JSON 並尋找 windowing 元素。