文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


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

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 元素。