ron*_*ran 4 sql-server user-defined-functions inline-functions table-functions
我使用AdventureWorks2012进行测试.和我的问题:为什么SELECT语句直接性能低于表值函数.我只将SELECT statemnt放入表值函数和完全相反的性能.
CREATE FUNCTION [dbo].[atest1]
(
@iBusinessEntityID INT
)
RETURNS @t TABLE
(
[BusinessEntityID] INT
, [NationalIDNumber] NVARCHAR(15)
, [JobTitle] NVARCHAR(50)
)
AS
BEGIN
INSERT INTO @t
SELECT
[e].[BusinessEntityID]
, [e].[NationalIDNumber]
, [e].[JobTitle]
FROM [HumanResources].[Employee] [e]
INNER JOIN [Person].[Person] [p]
ON [p].[BusinessEntityID] = [e].[BusinessEntityID]
WHERE [e].[BusinessEntityID] = @iBusinessEntityID;
RETURN;
END;
--TEST PERFORMANCE
SELECT
*
FROM [dbo].[atest1](5);
GO
SELECT
[e].[BusinessEntityID]
, [e].[NationalIDNumber]
, [e].[JobTitle]
FROM [HumanResources].[Employee] [e]
INNER JOIN [Person].[Person] [p]
ON [p].[BusinessEntityID] = [e].[BusinessEntityID]
WHERE [e].[BusinessEntityID] = 5;
Run Code Online (Sandbox Code Playgroud)
这里的问题是,估计的计划SSMS往往显示错误的百分比,如果是,UDF它几乎总是错误的.
这cost percentage是与其他操作相比的操作估计成本,但是如果UDF SSMS没有检查UDF的内部.
我UDF在我的服务器上创建了你的文本a GUID,所以我可以很容易地返回这个UDF的计划:
CREATE FUNCTION [dbo].[atest1] (@iBusinessEntityID int)
RETURNS @t TABLE(BusinessEntityID int,NationalIDNumber nvarchar(15),JobTitle nvarchar(50)) AS
BEGIN
INSERT INTO @t /*3C6A985B-748B-44D4-9F76-1A0866342728*/ -- HERE IS MY GUID
SELECT e.BusinessEntityID, e.NationalIDNumber, e.JobTitle
FROM HumanResources.Employee e INNER JOIN Person.Person p ON p.BusinessEntityID = e.BusinessEntityID
WHERE e.BusinessEntityID = @iBusinessEntityID
RETURN
END
Run Code Online (Sandbox Code Playgroud)
现在我执行此函数并以这种方式检索其计划:
select p.query_plan
from sys.dm_exec_cached_plans cp
cross apply sys.dm_exec_sql_text(cp.plan_handle) t
cross apply sys.dm_exec_query_plan(cp.plan_handle) p
where cp.objtype = 'Proc'
and t.text like '%3C6A985B-748B-44D4-9F76-1A0866342728%'
Run Code Online (Sandbox Code Playgroud)
我检查了这个计划,它正好是你的"直接声明"的计划.它的SELECT部分是相同的,但是INSERT在表格中还有一个变量scan在主计划中.因此,您可以清楚地看到您的UDF成本不能低,它等于"直接声明"成本加INSERT成本加表变量scan成本.
在这种情况下,表很小,只有一个UDF调用,所以你不能注意执行时间的差异,但如果你做一个循环执行你的"直接语句"更多次并调用UDF更多次你可能会看到执行时间差异,"直接声明"将更快.但无论如何SSMS都会坚持UDF降低成本.