Documentation Home
MySQL 8.0 参考手册  / 第8章优化  / 8.2 优化SQL语句  / 8.2.1 优化 SELECT 语句  /  8.2.1.21 窗口函数优化

8.2.1.21 窗口函数优化

窗口函数影响优化器考虑的策略:

  • 如果子查询具有窗口函数,则禁用子查询的派生表合并。子查询总是具体化的。

  • 半连接不适用于窗口函数优化,因为半连接适用于 WHERE和中的子查询JOIN ... 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

替换WHEREHAVING导致错误:

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)can 存在于 中HAVING,因此使外部查询聚合。

窗口函数(包括用作窗口函数的聚合函数)没有上述复杂度。它们总是聚合在写入它们的子查询中,从不聚合在外部查询中。

窗口函数评估可能会受到系统变量值的影响, windowing_use_high_precision 系统变量决定是否在不损失精度的情况下计算窗口操作。默认情况下, windowing_use_high_precision 启用。

对于某些移动帧聚合,可以应用逆聚合函数从聚合中删除值。这可以提高性能,但可能会降低精度。例如,将一个非常小的浮点值添加到一个非常大的值会导致非常小的值被 大值隐藏。稍后反转大值时,小值的效果将丢失。

由于反向聚合导致的精度损失仅适用于浮点(近似值)数据类型的操作。对于其他类型,反向聚合是安全的;这包括DECIMAL,它允许小数部分但是是精确值类型。

为了更快地执行,MySQL 在安全的情况下总是使用反向聚合:

  • 对于浮点值,反向聚合并不总是安全的,可能会导致精度损失。默认设置是避免反向聚合,它速度较慢但保留精度。如果允许为了速度牺牲安全性, windowing_use_high_precision 则可以禁用以允许反向聚合。

  • 对于非浮点数据类型,反向聚合始终是安全的,并且无论 windowing_use_high_precision 值如何都可以使用。

  • windowing_use_high_precisionMIN()和 没有影响MAX(),它们在任何情况下都不使用逆聚合。

对于方差函数 STDDEV_POP()STDDEV_SAMP()VAR_POP()VAR_SAMP()及其同义词的评估,评估可以在优化模式或默认模式下进行。优化模式可能会在最后的有效数字中产生略有不同的结果。如果允许此类差异, windowing_use_high_precision 则可以禁用以允许优化模式。

对于EXPLAIN,windowing 执行计划信息过于广泛,无法以传统的输出格式显示。要查看窗口信息,请使用 EXPLAIN FORMAT=JSON并查找该 windowing元素。