窗口函数优化
窗口函数会影响优化器考虑的策略:
- 如果子查询具有窗口功能,则禁用子查询的派生表合并。子查询始终是物化的。
- 半连接并不适用于窗口功能优化,因为半连接适用于子查询
WHERE
和JOIN ... ON
,这不能包含窗口函数。 - 优化器按顺序处理多个具有相同排序要求的窗口,因此可以跳过对第一个窗口之后的窗口的排序。
- 优化器不会尝试合并可以在单个步骤中评估的窗口(例如,当多个
OVER
子句包含相同的窗口定义时)。解决方法是在WINDOW
子句中定义窗口,并在子句中引用窗口名称OVER
。
在最外层可能的查询中汇总未用作窗口函数的汇总函数。例如,在此查询中,MySQL认为COUNT(t1.b)
外部查询中不存在某些内容,因为它在WHERE
子句中的位置:
SELECT *FROM t1WHERE t1. = (SELECT COUNT(t1.b)FROM t2);
因此,MySQL会在子查询内部进行汇总,将其t1.b
视为常量并返回的行数t2
。
更换WHERE
用HAVING
一个错误的结果:
mysql>SELECT *FROM t1HAVING t1. = (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
元素。