原文地址:https://oracle-base.com/articles/21c/any_value-21c
原文作者:Tim Hall
ANY_VALUE
函数
允许我们从 GROUP BY 子句中安全地删除列,以减少任何性能开销。
目录
环境准备
本文中的示例需要提前创建以下表和
数据
:
1 | |
问题描述
我们需要返回一个部门列表,其中包含部门中的员工数量,因此我们可以使用 COUNT 聚合函数和 GROUP BY 子句来实现:
1 | |
在 21C 以前的版本中,我们必须将所有非聚合列包含在 GROUP BY 条件中,否则将会报错且无法执行。由于我们并不关心 GROUP BY 中是否包含 DNAME 列,但是受制于语法必须得这样做,同时在 GROUP BY 中添加额外的列也会造成不必要的开销,为了避免这个问题,大家可能会使用 MIN 或者 MAX 函数。
1 | |
这种写法使得我们可以从 GROUP BY 中拿掉 DNAME 列,但是新增了 MIN 或者 MAX 函数造成了新的开销。
解决方案:ANY_VALUE
在 Oracle 21c 中引入了 ANY_VALUE 聚合函数来解决这个问题。
原理
同样是使用 MIN 或者 MAX 函数的方式,只是以 ANY_VALUE 进行替代,它不进行任何类型的比较,而是显示它找到的第一个非 NULL 值,但是经过内部优化可以做到最大幅度减少聚合函数的开销。
1 | |
所以现在我们可以减少 GROUP BY 中附加列的开销,而不必添加 MIN 或 MAX 函数的开销。
注意事项
- 它具有不确定性,所以不要在预设场景外使用此函数。
- 数据量小的情况下,我们可能无法观测到性能的改进,但随着数据量的增加,GROUP BY 或者使用 MIN 和 MAX 函数的开销必然超过 ANY_VALUE。
- 由于 MIN 和 MAX 函数是有确定意义的,如果代码编写者当时仅出于从 GROUP BY 中排除非必要列,非代码编写者读代码时可能对于该写法无法理解其用意,但是 ANY_VALUE 函数是非确定性的,因此使用它对任何其他开发人员来说都是一个明确的信息,即您正在使用它将列从 GROUP BY 中删除。从支持的角度来看,这种额外的清晰度是一件好事。
- ANY_VALUE 函数支持 ALL 和 DISTINCT 关键字,但它们没有任何功能。
- 表达式中的 NULL 值被忽略,因此 ANY_VALUE 将返回它找到的第一个非 NULL 值。如果表达式中的所有值都是 NULL,那么将返回 NULL 值。
- 它支持除 XMLTYPE、ANYDATA、LOB、文件或集合数据类型之外的任何数据类型,这会导致 ORA-00932 错误。
- 与大多数函数一样,输入表达式可以是列、常量、绑定变量或由它们组成的表达式。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Lucifer三思而后行!



