When multiple calls to the same UDF are in a single statement, how many times will it be called?(当在一个语句中多次调用同一个 UDF 时,它会被调用多少次?)
问题描述
在下面的 t-sql 语句中,dbo.FUNC 函数会被调用多少次?
In the following t-sql statement, how many times will the dbo.FUNC function get called?
SELECT
column1,
column2,
dbo.FUNC(column3) AS column3
FROM table1
WHERE dbo.FUNC(column3) >= 5
ORDER BY dbo.FUNC(column3) DESC
它会在每行中多次单独调用,还是优化器识别出它在单个语句中被多次使用,并且只调用一次?
Will it called multiple separate times per row, or does the optimizer recognize that it is being used multiple times in a single statement, and only call it once?
我该如何测试?我无法插入到函数内部的表中,因此递增计数器不起作用...
How can I test this? I can't insert into a table inside of a function, so incrementing a counter wont work...
推荐答案
这不能保证.
您需要检查执行计划才能找到答案.一些例子.
You would need to check the execution plan to find out. Some examples.
CREATE FUNCTION dbo.FUNC1(@p1 int)
RETURNS int
AS
BEGIN
RETURN @p1 + 1
END
GO
CREATE FUNCTION dbo.FUNC2(@p1 int)
RETURNS int
WITH SCHEMABINDING
AS
BEGIN
RETURN @p1 + 1
END
GO
SELECT
OBJECTPROPERTYEX(OBJECT_ID('dbo.FUNC1'), 'IsDeterministic'),
OBJECTPROPERTYEX(OBJECT_ID('dbo.FUNC2'), 'IsDeterministic')
GO
FUNC2 创建 WITH SCHEMABINDING 并被视为确定性的.FUNC1 不是.
FUNC2 is created WITH SCHEMABINDING and is treated as deterministic. FUNC1 isn't.
SELECT
dbo.FUNC1(number) AS FUNC1,
dbo.FUNC2(number) AS FUNC2
FROM master..spt_values
WHERE dbo.FUNC1(number) >= 5 AND dbo.FUNC2(number) >= 5
ORDER BY dbo.FUNC1(number), dbo.FUNC2(number)
提供计划
|--Sort(ORDER BY:([Expr1003] ASC, [Expr1004] ASC))
|--Compute Scalar(DEFINE:([Expr1003]=[test].[dbo].[FUNC1]([master].[dbo].[spt_values].[number])))
|--Filter(WHERE:([test].[dbo].[FUNC1]([master].[dbo].[spt_values].[number])>=(5) AND [Expr1004]>=(5)))
|--Compute Scalar(DEFINE:([Expr1004]=[test].[dbo].[FUNC2]([master].[dbo].[spt_values].[number])))
|--Index Scan(OBJECT:([master].[dbo].[spt_values].[ix2_spt_values_nu_nc]))
FUNC1 被评估两次(一次在过滤器中,一次在计算标量中输出用于投影和排序的计算列),FUNC2 只被评估一次.
FUNC1 is evaluated twice (once in the filter and once in a compute scalar outputting a calculated column used for both the projection and the ordering), FUNC2 is only evaluated once.
重写为
SELECT
FUNC1,
FUNC2
FROM master..spt_values
CROSS APPLY (SELECT dbo.FUNC1(number), dbo.FUNC2(number)) C(FUNC1, FUNC2)
WHERE FUNC1 >= 5 AND FUNC2 >= 5
ORDER BY FUNC1, FUNC2
稍微改变计划,两者都只评估一次
Changes the plan slightly and both are only evaluated once
|--Sort(ORDER BY:([Expr1003] ASC, [Expr1004] ASC))
|--Filter(WHERE:([Expr1003]>=(5)))
|--Compute Scalar(DEFINE:([Expr1003]=[test].[dbo].[FUNC1]([master].[dbo].[spt_values].[number])))
|--Filter(WHERE:([Expr1004]>=(5)))
|--Compute Scalar(DEFINE:([Expr1004]=[test].[dbo].[FUNC2]([master].[dbo].[spt_values].[number])))
|--Index Scan(OBJECT:([master].[dbo].[spt_values].[ix2_spt_values_nu_nc]))
现在对查询稍作改动
SELECT
FUNC1 + 10,
FUNC2 + 10
FROM master..spt_values
CROSS APPLY (SELECT dbo.FUNC1(number), dbo.FUNC2(number)) C(FUNC1, FUNC2)
WHERE FUNC1 >= 5 AND FUNC2 >= 5
ORDER BY FUNC1, FUNC2
给出与原始结果相反的结果,即 FUNC2 计算两次,而 FUNC1 只计算一次.
Gives the opposite of the original result in that FUNC2 is evaluated twice but FUNC1 only once.
|--Compute Scalar(DEFINE:([Expr1005]=[Expr1003]+(10)))
|--Sort(ORDER BY:([Expr1003] ASC, [Expr1004] ASC))
|--Filter(WHERE:([Expr1003]>=(5)))
|--Compute Scalar(DEFINE:([Expr1003]=[test].[dbo].[FUNC1]([master].[dbo].[spt_values].[number])))
|--Filter(WHERE:([Expr1004]>=(5)))
|--Compute Scalar(DEFINE:([Expr1004]=[test].[dbo].[FUNC2]([master].[dbo].[spt_values].[number]), [Expr1006]=[test].[dbo].[FUNC2]([master].[dbo].[spt_values].[number])+(10)))
|--Index Scan(OBJECT:([master].[dbo].[spt_values].[ix2_spt_values_nu_nc]))
这篇关于当在一个语句中多次调用同一个 UDF 时,它会被调用多少次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:当在一个语句中多次调用同一个 UDF 时,它会被调
基础教程推荐
- 带有WHERE子句的LAG()函数 2022-01-01
- CHECKSUM 和 CHECKSUM_AGG:算法是什么? 2021-01-01
- 使用 VBS 和注册表来确定安装了哪个版本和 32 位 2021-01-01
- ORA-01830:日期格式图片在转换整个输入字符串之前结束/选择日期查询的总和 2021-01-01
- 从字符串 TSQL 中获取数字 2021-01-01
- MySQL 5.7参照时间戳生成日期列 2022-01-01
- MySQL根据从其他列分组的值,对两列之间的值进行求和 2022-01-01
- while 在触发器内循环以遍历 sql 中表的所有列 2022-01-01
- 带更新的 sqlite CTE 2022-01-01
- 如何在 CakePHP 3 中实现 INSERT ON DUPLICATE KEY UPDATE aka upsert? 2021-01-01
