文档首页
MySQL 8.4 参考手册
相关文档 下载此手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (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 的行数。

HAVING 替换 WHERE 会导致错误

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_precisionMIN()MAX() 没有影响,它们在任何情况下都不会使用逆聚合。

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

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